]> 4ch.mooo.com Git - 16.git/commitdiff
Merge remote-tracking branch 'upstream/master'
authorJonathan Campbell <jonathan@castus.tv>
Fri, 21 Oct 2016 19:10:17 +0000 (12:10 -0700)
committerJonathan Campbell <jonathan@castus.tv>
Fri, 21 Oct 2016 19:10:17 +0000 (12:10 -0700)
84 files changed:
16/16_mm.c [new file with mode: 0755]
DEBUG.16B
DEBUG.16W
DEBUG_.16W [deleted file]
HEAP.16W
MMDUMP.16B
MMDUMP.16W
PROFILE.16W [new file with mode: 0755]
bcexmm.dsk
bcexmm.exe
bcexmm.prj
data/g.pal
fmemtest.exe [new file with mode: 0755]
fontgfx.exe [new file with mode: 0755]
fonttest.exe [new file with mode: 0755]
inputest.exe [new file with mode: 0755]
makefile
maptest.exe [new file with mode: 0755]
modex.lib [deleted file]
pcxtest.exe [new file with mode: 0755]
pcxtest2.exe [new file with mode: 0755]
pm.use [new file with mode: 0755]
src/0.c
src/16.ses
src/_scroll.c
src/bakapi.c
src/bakapi.h
src/emmtest.c
src/emsdump.c
src/emstest.c
src/exmmtest.c
src/inputest.c
src/lib/16_ca.c
src/lib/16_dbg.c
src/lib/16_dbg.h
src/lib/16_hc.c
src/lib/16_hc.h
src/lib/16_head.c
src/lib/16_head.h
src/lib/16_in.c
src/lib/16_in.h
src/lib/16_map.c
src/lib/16_mm.c
src/lib/16_mm.h
src/lib/16_pm.c
src/lib/16_pm.h
src/lib/16_sprit.c
src/lib/16_sprit.h
src/lib/16_tail.c [new file with mode: 0755]
src/lib/16_tail.h [new file with mode: 0755]
src/lib/16_vrs.c
src/lib/16_vrs.h
src/lib/_croll16.c
src/lib/bakapee.c
src/lib/ems.c
src/lib/ems.h
src/lib/jsmn
src/lib/mapread.c
src/lib/midi.c
src/lib/midi.h
src/lib/modex16.h
src/lib/scroll16.c
src/lib/scroll16.h
src/lib/typdefst.h
src/lib/types.h
src/lib/xms.c
src/lib/xms.h
src/lib/zcroll16.c [new file with mode: 0755]
src/lib/zcroll16.h [new file with mode: 0755]
src/midi.c
src/miditest.c
src/scroll.c
src/testemm.c
src/testemm0.c
src/testsnd.c
src/tesuto.c
src/tesuto.h
src/tsthimem.c
src/vrstest.c
src/zcroll.c
test.exe [new file with mode: 0755]
test0.exe [new file with mode: 0755]
vgmtest.exe [new file with mode: 0755]
wolf3dpm.png [new file with mode: 0755]

diff --git a/16/16_mm.c b/16/16_mm.c
new file mode 100755 (executable)
index 0000000..9f10fd3
--- /dev/null
@@ -0,0 +1,1802 @@
+/* Catacomb Apocalypse Source Code\r
+ * Copyright (C) 1993-2014 Flat Rock Software\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ */\r
+\r
+// NEWMM.C\r
+\r
+/*\r
+=============================================================================\r
+\r
+                       ID software memory manager\r
+                       --------------------------\r
+\r
+Primary coder: John Carmack\r
+\r
+RELIES ON\r
+---------\r
+Quit (char *error) function\r
+\r
+\r
+WORK TO DO\r
+----------\r
+MM_SizePtr to change the size of a given pointer\r
+\r
+Multiple purge levels utilized\r
+\r
+EMS / XMS unmanaged routines\r
+\r
+=============================================================================\r
+*/\r
+/*\r
+\r
+Open Watcom port by sparky4\r
+\r
+*/\r
+#include "src/lib/16_mm.h"\r
+#include "src/lib/16_ca.h"\r
+#pragma hdrstop\r
+\r
+#pragma warn -pro\r
+#pragma warn -use\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+void           (* beforesort) (void);\r
+void           (* aftersort) (void);\r
+void           (* XMSaddr) (void);             // far pointer to XMS driver\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+/*\r
+======================\r
+=\r
+= MML_CheckForEMS\r
+=\r
+= Routine from p36 of Extending DOS\r
+=\r
+=======================\r
+*/\r
+\r
+boolean MML_CheckForEMS(void)\r
+{\r
+       boolean emmcfems;\r
+       static char     emmname[] = "EMMXXXX0"; //fix by andrius4669\r
+       __asm {\r
+               mov     dx,OFFSET emmname       //fix by andrius4669\r
+               mov     ax,0x3d00\r
+               int     0x21            // try to open EMMXXXX0 device\r
+               jc      error\r
+\r
+               mov     bx,ax\r
+               mov     ax,0x4400\r
+\r
+               int     0x21            // get device info\r
+               jc      error\r
+\r
+               and     dx,0x80\r
+               jz      error\r
+\r
+               mov     ax,0x4407\r
+\r
+               int     0x21            // get status\r
+               jc      error\r
+               or      al,al\r
+               jz      error\r
+\r
+               mov     ah,0x3e\r
+               int     0x21            // close handle\r
+               jc      error\r
+               //\r
+               // EMS is good\r
+               //\r
+               mov     emmcfems,1\r
+               jmp End\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               error:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               //\r
+               // EMS is bad\r
+               //\r
+               mov     emmcfems,0\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               End:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       return(emmcfems);\r
+}\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MML_SetupEMS\r
+=\r
+=======================\r
+*/\r
+\r
+byte MML_SetupEMS(global_game_variables_t *gvar)\r
+{\r
+       byte    str[160];\r
+       byte    err;\r
+       boolean errorflag=false;\r
+\r
+       unsigned int EMSVer = 0;\r
+       //byte  EMS_status;\r
+       unsigned        totalEMSpages,freeEMSpages,EMSPageFrame,EMSpagesmapped,EMSHandle;\r
+       totalEMSpages = freeEMSpages = EMSPageFrame = EMSpagesmapped = 0;\r
+\r
+       __asm {\r
+               mov     ah,EMS_STATUS\r
+               int     EMS_INT                                         // make sure EMS hardware is present\r
+               or      ah,ah\r
+               //mov   [EMS_status],ah\r
+               jnz     error\r
+\r
+               mov     ah,EMS_VERSION\r
+               int     EMS_INT\r
+               or      ah,ah\r
+               jnz     error\r
+               mov     [EMSVer],ax                             //      set EMSVer\r
+               cmp     al,0x32                                         // only work on ems 3.2 or greater\r
+               jb      error\r
+\r
+               mov     ah,EMS_GETFRAME\r
+               int     EMS_INT                                         // find the page frame address\r
+               or      ah,ah\r
+               jnz     error\r
+               mov     [EMSPageFrame],bx\r
+\r
+               mov     ah,EMS_GETPAGES\r
+               int     EMS_INT                                         // find out how much EMS is there\r
+               or      ah,ah\r
+               jnz     error\r
+               mov     [totalEMSpages],dx\r
+               mov     [freeEMSpages],bx\r
+               or      bx,bx\r
+               jz      noEMS                                           // no EMS at all to allocate\r
+                                                                                       //EXPAND DONG!!!!\r
+               cmp     [EMSVer],0x40\r
+               jb      low\r
+               cmp     bx,[freeEMSpages]\r
+               jle     getpages\r
+               mov     bx,[freeEMSpages]\r
+               jmp     getpages\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       low:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               cmp     bx,4\r
+               jle     getpages                                        // there is only 1,2,3,or 4 pages\r
+               mov     bx,4                                            // we can't use more than 4 pages\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       getpages:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     [EMSpagesmapped],bx\r
+               mov     ah,EMS_ALLOCPAGES                       // allocate up to 64k of EMS\r
+               int     EMS_INT\r
+               or      ah,ah\r
+               jnz     error\r
+               mov     [EMSHandle],dx\r
+               jmp End\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       error:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     err,ah\r
+               mov     errorflag,1\r
+               jmp End\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+noEMS:\r
+End:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       if(errorflag==true)\r
+       {\r
+               strcpy(str,"MM_SetupEMS: EMS error ");\r
+               MM_EMSerr(str, err);\r
+               printf("%s\n",str);\r
+               return err;\r
+       }\r
+       gvar->pm.emm.totalEMSpages=totalEMSpages;\r
+       gvar->pm.emm.freeEMSpages=freeEMSpages;\r
+       gvar->pm.emm.EMSPageFrame=EMSPageFrame;\r
+       gvar->pm.emm.EMSpagesmapped=EMSpagesmapped;\r
+       gvar->pm.emm.EMSHandle=EMSHandle;\r
+       gvar->pm.emm.EMSVer=EMSVer;\r
+       return 0;\r
+}\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MML_ShutdownEMS\r
+=\r
+=======================\r
+*/\r
+\r
+void MML_ShutdownEMS(global_game_variables_t *gvar)\r
+{\r
+       boolean errorflag=false;\r
+       unsigned EMSHandle=gvar->pm.emm.EMSHandle;\r
+\r
+       if(!EMSHandle)\r
+               return;\r
+       __asm {\r
+               mov     ah,EMS_FREEPAGES\r
+               mov     dx,[EMSHandle]\r
+               int     EMS_INT\r
+               or      ah,ah\r
+               jz      ok\r
+               mov     errorflag,1\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               ok:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       if(errorflag==true)\r
+               Quit("MML_ShutdownEMS: Error freeing EMS!\n");  //++++ add something\r
+}\r
+\r
+/*\r
+====================\r
+=\r
+= MM_MapEMS\r
+=\r
+= Maps the 64k of EMS used by memory manager into the page frame\r
+= for general use.  This only needs to be called if you are keeping\r
+= other things in EMS.\r
+=\r
+====================\r
+*/\r
+\r
+byte MM_MapEMS(global_game_variables_t *gvar)\r
+{\r
+       byte    str[160];\r
+       unsigned        EMSHandle;\r
+       byte err;\r
+       boolean errorflag=false;\r
+       int     i;\r
+       EMSHandle=gvar->pm.emm.EMSHandle;\r
+\r
+       for (i=0;i<4/*MAPPAGES*/;i++)\r
+       {\r
+               __asm {\r
+                       mov     ah,EMS_MAPPAGE\r
+                       mov     bx,[i]                  // logical page\r
+                       mov     al,bl                   // physical page\r
+                       mov     dx,[EMSHandle]  // handle\r
+                       int     EMS_INT\r
+                       or      ah,ah\r
+                       jnz     error\r
+                       jmp End\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       error:\r
+#ifdef __BORLANDC__\r
+               __asm {\r
+#endif\r
+                       mov     err,ah\r
+                       mov     errorflag,1\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       End:\r
+#ifdef __WATCOMC__\r
+               }\r
+#endif\r
+               if(errorflag==true)\r
+               {\r
+                       strcpy(str,"MM_MapEMS: EMS error ");\r
+                       MM_EMSerr(str, err);\r
+                       printf("%s\n",str);\r
+                       return err;\r
+               }\r
+       }\r
+       gvar->mmi.EMSmem = (i)*0x4000lu;\r
+       //printf("              gvar->mmi.EMSmem=%lu\n", gvar->mmi.EMSmem);\r
+       return 0;\r
+}\r
+\r
+byte MM_MapXEMS(global_game_variables_t *gvar)\r
+{\r
+//SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)\r
+\r
+       //Maps up to 4 logical EMS pages to physical pages in the page frame, where:\r
+       //PhysicalStart = Physical page first logical page is mapped to\r
+       //LogicalStart  = First logical page to map\r
+       //NumPages      = Number of pages to map (1 to 4)\r
+       //Handle        = EMS handle logical pages are allocated to\r
+\r
+  /*//Create a buffer containing the page information\r
+//  FOR x = 0 TO NumPages - 1\r
+//    MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x)\r
+//  NEXT*/\r
+\r
+//  Regs.ax = 0x5000                           //Map the pages in the buffer\r
+//  Regs.cx = NumPages                         //to the pageframe\r
+//  Regs.dx = Handle\r
+//  Regs.ds = VARSEG(MapInfo$)\r
+//  Regs.si = SADD(MapInfo$)\r
+//  InterruptX 0x67, Regs, Regs\r
+//     EMS.Error = (Regs.ax AND 0xFF00&) \ 0x100  //Store the status code\r
+\r
+//END SUB\r
+       byte    str[160];\r
+       byte err;\r
+       word    EMSHandle;\r
+       boolean errorflag=false;\r
+       int     i;\r
+       EMSHandle=gvar->pm.emm.EMSHandle;\r
+\r
+       if(gvar->pm.emm.EMSVer<0x40)\r
+               return 5;\r
+\r
+       for (i=0;i<MAPPAGES;i++)\r
+       {\r
+               __asm {\r
+                       mov     ah,EMS_MAPXPAGE\r
+                       mov     cx,[i]                  // logical page\r
+                       mov     al,bl                   // physical page\r
+                       mov     dx,[EMSHandle]  // handle\r
+                       int     EMS_INT\r
+                       or      ah,ah\r
+                       jnz     error\r
+                       jmp End\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       error:\r
+#ifdef __BORLANDC__\r
+               __asm {\r
+#endif\r
+                       mov     err,ah\r
+                       mov     errorflag,1\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       End:\r
+#ifdef __WATCOMC__\r
+               }\r
+#endif\r
+               if(errorflag==true)\r
+               {\r
+                       //strcpy(str,"MM_MapXEMS: EMS error 0x");\r
+                       strcpy(str,"MM_MapXEMS: EMS error ");\r
+                       //itoa(err,str2,16);\r
+                       MM_EMSerr(str, err);\r
+                       printf("%s\n",str);\r
+                       //printf("%s%x\n",str, err);\r
+                       //printf("FACK! %x\n", err);\r
+                       return err;\r
+               }\r
+       }\r
+       gvar->mmi.EMSmem = (i)*0x4000lu;\r
+       return 0;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+======================\r
+=\r
+= MML_CheckForXMS\r
+=\r
+= Check for XMM driver\r
+=\r
+=======================\r
+*/\r
+\r
+boolean MML_CheckForXMS(global_game_variables_t *gvar)\r
+{\r
+       boolean errorflag=false;\r
+       gvar->mm.numUMBs = 0;\r
+\r
+       __asm {\r
+               mov     ax,0x4300\r
+               int     0x2f                            // query status of installed diver\r
+               cmp     al,0x80\r
+               je      good\r
+               mov     errorflag,1\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               good:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       if(errorflag==true) return false;\r
+       else return true;\r
+}\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MML_SetupXMS\r
+=\r
+= Try to allocate all upper memory block\r
+=\r
+=======================\r
+*/\r
+\r
+void MML_SetupXMS(global_game_variables_t *gvar)\r
+{\r
+       word    base,size;\r
+\r
+\r
+       __asm {\r
+               mov     ax,0x4310\r
+               int     0x2f\r
+               mov     [WORD PTR XMSaddr],bx\r
+               mov     [WORD PTR XMSaddr+2],es         // function pointer to XMS driver\r
+       }\r
+getmemory:\r
+       __asm {\r
+               mov     ah,XMS_ALLOCUMB\r
+               mov     dx,0xffff                                       // try for largest block possible\r
+               //mov     ax,dx                                         // Set available Kbytes.\r
+               call    [DWORD PTR XMSaddr]\r
+               or      ax,ax\r
+               jnz     gotone\r
+\r
+               cmp     bl,0xb0                                         // error: smaller UMB is available\r
+               jne     done;\r
+\r
+               mov     ah,XMS_ALLOCUMB\r
+               call    [DWORD PTR XMSaddr]             // DX holds largest available UMB\r
+               or      ax,ax\r
+               jz      done                                            // another error...\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               gotone:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     [base],bx\r
+               mov     [size],dx\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               done:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+//     printf("base=%u ", base); printf("size=%u\n", size);\r
+       MML_UseSpace(base,size, gvar);\r
+       gvar->mmi.XMSmem += size*16;\r
+       gvar->mm.UMBbase[gvar->mm.numUMBs] = base;\r
+       gvar->mm.numUMBs++;\r
+       if(gvar->mm.numUMBs < MAXUMBS)\r
+               goto getmemory;\r
+}\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MML_ShutdownXMS\r
+=\r
+======================\r
+*/\r
+\r
+void MML_ShutdownXMS(global_game_variables_t *gvar)\r
+{\r
+       int     i;\r
+       unsigned        base;\r
+\r
+       for (i=0;i<gvar->mm.numUMBs;i++)\r
+       {\r
+               base = gvar->mm.UMBbase[i];\r
+               __asm {\r
+                       mov     ah,XMS_FREEUMB\r
+                       mov     dx,[base]\r
+                       call    [DWORD PTR XMSaddr]\r
+               }\r
+       }\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+======================\r
+=\r
+= MML_UseSpace\r
+=\r
+= Marks a range of paragraphs as usable by the memory manager\r
+= This is used to mark space for the near heap, far heap, ems page frame,\r
+= and upper memory blocks\r
+=\r
+======================\r
+*/\r
+\r
+/*void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *last;\r
+       word            segm=1;\r
+       word    oldend;\r
+       dword           segmlen;\r
+       dword           extra;\r
+\r
+       scan = last = gvar->mm.mmhead;\r
+       gvar->mm.mmrover = gvar->mm.mmhead;             // reset rover to start of memory\r
+\r
+//\r
+// search for the block that contains the range of segments\r
+//\r
+       while(scan->start+scan->length < segstart)\r
+       {\r
+               last = scan;\r
+               scan = scan->next;\r
+       }\r
+\r
+//\r
+// take the given range out of the block\r
+//\r
+       oldend = scan->start + scan->length;\r
+       extra = oldend - (segstart+seglength);\r
+\r
+       segmlen=extra;\r
+\r
+       //++++emsver stuff!\r
+       if(segm>1)/// || extra>=0x10000lu)\r
+       //if(extra>0xfffflu)\r
+       {\r
+               scan->blob=segm;\r
+\r
+               //MML_UseSpace(segstart, seglength, gvar);\r
+\r
+               printf("MML_UseSpace: Segment spans two blocks!\n");\r
+       //}\r
+       printf("segm=%u         ", segm);\r
+       printf("ex=%lu  ", extra);\r
+       printf("old=%u  ", oldend);\r
+       printf("start+seglen=%lu\n", segstart+seglength);\r
+       printf("segsta=%x       ", segstart);\r
+       printf("len=%lu ", scan->length);\r
+       printf("seglen=%lu      ", seglength);\r
+       printf("segmlen=%lu\n", segmlen);\r
+       }\r
+//++++todo: linked list of segment!\r
+       if(segstart == scan->start)\r
+       {\r
+               last->next = scan->next;                        // unlink block\r
+               FREEBLOCK(scan);\r
+               scan = last;\r
+       }\r
+       else\r
+               scan->length = segstart-scan->start;    // shorten block\r
+\r
+       if(extra > 0)\r
+       {\r
+               GETNEWBLOCK;\r
+               gvar->mm.mmnew->useptr = NULL;\r
+\r
+               gvar->mm.mmnew->next = scan->next;\r
+               scan->next = gvar->mm.mmnew;\r
+               gvar->mm.mmnew->start = segstart+seglength;\r
+               gvar->mm.mmnew->length = extra;\r
+               gvar->mm.mmnew->attributes = LOCKBIT;\r
+       }//else if(segm>0) goto segu;\r
+\r
+}*/\r
+void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)\r
+{\r
+       mmblocktype far *scan,far *last;\r
+       word    oldend;\r
+       sdword          extra;\r
+       //word segm=1;\r
+\r
+       scan = last = gvar->mm.mmhead;\r
+       gvar->mm.mmrover = gvar->mm.mmhead;             // reset rover to start of memory\r
+\r
+//\r
+// search for the block that contains the range of segments\r
+//\r
+       while (scan->start+scan->length < segstart)\r
+       {\r
+               last = scan;\r
+               scan = scan->next;\r
+       }\r
+\r
+//\r
+// find out how many blocks it spans!\r
+//\r
+       /*for(;seglength>=0x10000;seglength-=0xFFFF)\r
+       {\r
+               //printf("      seglen=%lu\n", segmlen);\r
+               segm++;\r
+       }*/\r
+\r
+//\r
+// take the given range out of the block\r
+//\r
+       oldend = scan->start + scan->length;\r
+       extra = oldend - (segstart+((unsigned)seglength));\r
+       if (extra < 0)\r
+       {\r
+               printf("========================================\n");\r
+               printf("start=%x        ", scan->start);\r
+               printf("old=%u  ", oldend);\r
+               printf("start+seglen=%lu\n", segstart+seglength);\r
+               printf("segsta=%x       ", segstart);\r
+               printf("len=%lu ", scan->length);\r
+               printf("seglen=%lu      ", seglength);\r
+               printf("\n");\r
+               printf("MML_UseSpace: Segment spans two blocks! %d\n", extra);\r
+               printf("========================================\n");\r
+               //return;\r
+       }\r
+\r
+       if (segstart == scan->start)\r
+       {\r
+               last->next = scan->next;                        // unlink block\r
+               FREEBLOCK(scan);\r
+               scan = last;\r
+       }\r
+       else\r
+               scan->length = segstart-scan->start;    // shorten block\r
+\r
+       if (extra > 0)\r
+       {\r
+               GETNEWBLOCK;\r
+               gvar->mm.mmnew->useptr = NULL;\r
+\r
+               gvar->mm.mmnew->next = scan->next;\r
+               scan->next = gvar->mm.mmnew;\r
+               gvar->mm.mmnew->start = segstart+seglength;\r
+               gvar->mm.mmnew->length = extra;\r
+               gvar->mm.mmnew->attributes = LOCKBIT;\r
+       }\r
+\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= MML_ClearBlock\r
+=\r
+= We are out of blocks, so free a purgable block\r
+=\r
+====================\r
+*/\r
+\r
+void MML_ClearBlock(global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *last;\r
+       mmblocktype far *scan,far *last;\r
+\r
+       scan = gvar->mm.mmhead->next;\r
+\r
+       while(scan)\r
+       {\r
+               if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS))\r
+               {\r
+                       MM_FreePtr(scan->useptr, gvar);\r
+                       return;\r
+               }\r
+               scan = scan->next;\r
+       }\r
+\r
+       printf("MM_ClearBlock: No purgable blocks!\n");\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= MM_Startup\r
+=\r
+= Grabs all space from turbo with malloc/farmalloc\r
+= Allocates bufferseg misc buffer\r
+=\r
+===================\r
+*/\r
+\r
+void MM_Startup(global_game_variables_t *gvar)\r
+{\r
+       int i;\r
+       //dword length,seglength;\r
+       dword length;\r
+       //huge void huge        *start;\r
+       void far        *start;\r
+       word    segstart,seglength,endfree;\r
+       //memptr *peeonself;\r
+\r
+       if(gvar->mm.mmstarted)\r
+               MM_Shutdown(gvar);\r
+\r
+\r
+       gvar->mm.mmstarted = true;\r
+       gvar->mm.bombonerror = true;\r
+//\r
+// set up the linked list (everything in the free list;\r
+//\r
+       gvar->mm.mmhead = NULL;\r
+       gvar->mm.mmfree = &(gvar->mm.mmblocks[0]);\r
+       for(i=0;i<MAXBLOCKS-1;i++)\r
+       {\r
+               gvar->mm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]);\r
+       }\r
+       gvar->mm.mmblocks[i].next = NULL;\r
+\r
+//\r
+// locked block of all memory until we punch out free space\r
+//\r
+       GETNEWBLOCK;\r
+       gvar->mm.mmhead = gvar->mm.mmnew;                               // this will allways be the first node\r
+       gvar->mm.mmnew->start = 0;\r
+       gvar->mm.mmnew->length = 0xffff;\r
+       gvar->mm.mmnew->attributes = LOCKBIT;\r
+       gvar->mm.mmnew->next = NULL;\r
+       //gvar->mm.mmnew->useptr = peeonself;\r
+       gvar->mm.mmrover = gvar->mm.mmhead;\r
+\r
+       //printf("              %x\n", peeonself);\r
+       //printf("              %x\n", *peeonself);\r
+//\r
+// get all available near conventional memory segments\r
+//\r
+#ifdef __WATCOMC__\r
+       _nheapgrow();\r
+       length=(dword)_memavl();//(dword)GetFreeSize();\r
+       //huge start = (void huge *)(gvar->mm.nearheap = _nmalloc(length));\r
+       start = (void far *)(gvar->mm.nearheap = _nmalloc(length));\r
+#endif\r
+#ifdef __BORLANDC__\r
+       length=coreleft();\r
+       //huge start = (void huge *)(gvar->mm.nearheap = malloc(length));\r
+       start = (void far *)(gvar->mm.nearheap = malloc(length));\r
+       printf("Borland C unique function\n");\r
+       printf("        coreleft()                              %lu\n", coreleft());\r
+#endif\r
+       length -= 16-(FP_OFF(start)&15);\r
+       length -= SAVENEARHEAP;\r
+       seglength = length / 16;                        // now in paragraphs\r
+       segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
+       MML_UseSpace(segstart,seglength, gvar);\r
+       gvar->mmi.nearheap = length;\r
+       //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);\r
+\r
+//\r
+// get all available far conventional memory segments\r
+//\r
+       //printf("_FARCORELEFT                          %lu\n", _FCORELEFT);\r
+#ifdef __WATCOMC__\r
+       _fheapgrow();\r
+#endif\r
+#ifdef __BORLANDC__\r
+       printf("        farcoreleft()                           %lu\n", farcoreleft());\r
+       printf("        (farcoreleft()+32)-_FCORELEFT   %d\n", (sword)((farcoreleft()+32)-_FCORELEFT));\r
+#endif\r
+       length=_FCORELEFT;//_fcoreleft();//(dword)GetFarFreeSize();//0xffffUL*4UL;\r
+       start = gvar->mm.farheap = _fmalloc(length);\r
+       //start = gvar->mm.farheap = halloc(length, 1);\r
+       length -= 16-(FP_OFF(start)&15);\r
+       length -= SAVEFARHEAP;\r
+       seglength = length / 16;                        // now in paragraphs\r
+       segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
+       MML_UseSpace(segstart,seglength, gvar);\r
+       gvar->mmi.farheap = length;\r
+       gvar->mmi.mainmem = gvar->mmi.nearheap + gvar->mmi.farheap;\r
+       //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);\r
+\r
+#ifdef __DEBUG_PM__\r
+goto xmsskip;  //INFO: 16_PM dose this job better\r
+#endif\r
+\r
+//\r
+// detect EMS and allocate up to 64K at page frame\r
+//\r
+       gvar->mmi.EMSmem = 0;\r
+//goto emsskip;        //0000\r
+       if(MML_CheckForEMS())\r
+       {\r
+               MML_SetupEMS(gvar);                                     // allocate space\r
+               //TODO: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT!\r
+               MML_UseSpace(gvar->pm.emm.EMSPageFrame,(MAPPAGES)*0x4000lu, gvar);\r
+               //if(gvar->pm.emm.EMSVer<0x40)\r
+                       MM_MapEMS(gvar);                                        // map in used pages\r
+               //else\r
+                       //MM_MapXEMS(gvar);                                     // map in used pages\r
+       }\r
+\r
+//\r
+// detect XMS and get upper memory blocks\r
+//\r
+//emsskip:\r
+       gvar->mmi.XMSmem = 0;\r
+goto xmsskip;//0000\r
+       if(MML_CheckForXMS(gvar))\r
+       {\r
+               MML_SetupXMS(gvar);                                     // allocate as many UMBs as possible\r
+       }\r
+\r
+//\r
+// allocate the misc buffer\r
+//\r
+xmsskip:\r
+       gvar->mm.mmrover = gvar->mm.mmhead;             // start looking for space after low block\r
+\r
+       MM_GetPtr(&(gvar->mm.bufferseg),BUFFERSIZE, gvar);\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= MM_Shutdown\r
+=\r
+= Frees all conventional, EMS, and XMS allocated\r
+=\r
+====================\r
+*/\r
+\r
+void MM_Shutdown(global_game_variables_t *gvar)\r
+{\r
+       if(!(gvar->mm.mmstarted))\r
+               return;\r
+\r
+       _ffree(gvar->mm.farheap);//     printf("                far freed\n");\r
+#ifdef __WATCOMC__\r
+       _nfree(gvar->mm.nearheap);//    printf("                near freed\n");\r
+#endif\r
+#ifdef __BORLANDC__\r
+       free(gvar->mm.nearheap);//      printf("                near freed\n");\r
+#endif\r
+#ifndef __DEBUG_PM__\r
+       if(MML_CheckForEMS()){ MML_ShutdownEMS(gvar); }//printf("               EMS freed\n"); }\r
+       if(MML_CheckForXMS(gvar)){ MML_ShutdownXMS(gvar); }//printf("           XMS freed\n"); }        //INFO: 16_PM dose this job better\r
+#endif\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= MM_GetPtr\r
+=\r
+= Allocates an unlocked, unpurgable block\r
+=\r
+====================\r
+*/\r
+\r
+void MM_GetPtr (memptr *baseptr, dword size, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *lastscan,huge *endscan,huge *purge,huge *next;\r
+       mmblocktype far *scan,far *lastscan,far *endscan,far *purge,far *next;\r
+       int                     search;\r
+       unsigned        needed,startseg;\r
+\r
+       needed = (size+15)/16;          // convert size from bytes to paragraphs\r
+\r
+       GETNEWBLOCK;                            // fill in start and next after a spot is found\r
+       gvar->mm.mmnew->length = needed;\r
+       gvar->mm.mmnew->useptr = baseptr;\r
+       //if(gvar->mm.mmnew->useptr==NULL){\r
+#ifdef __DEBUG__\r
+               printf("        MM_GetPtr\n");\r
+               printf("                baseptr=%04x    ", baseptr); printf("useptr=%04x\n", gvar->mm.mmnew->useptr);\r
+               printf("                *baseptr=%04x   ", *baseptr); printf("*useptr=%04x\n", *(gvar->mm.mmnew->useptr));\r
+               printf("                *baseptr=%Fp    ", *baseptr); printf("*useptr=%Fp\n", *(gvar->mm.mmnew->useptr));\r
+#endif\r
+       //exit(-5); }\r
+       gvar->mm.mmnew->attributes = BASEATTRIBUTES;\r
+\r
+//tryagain:\r
+       for (search = 0; search<3; search++)\r
+       {\r
+       //\r
+       // first search:        try to allocate right after the rover, then on up\r
+       // second search:       search from the head pointer up to the rover\r
+       // third search:        compress memory, then scan from start\r
+               if (search == 1 && gvar->mm.mmrover == gvar->mm.mmhead)\r
+                       search++;\r
+\r
+               switch (search)\r
+               {\r
+               case 0:\r
+                       lastscan = gvar->mm.mmrover;\r
+                       scan = gvar->mm.mmrover->next;\r
+                       endscan = NULL;\r
+                       break;\r
+               case 1:\r
+                       lastscan = gvar->mm.mmhead;\r
+                       scan = gvar->mm.mmhead->next;\r
+                       endscan = gvar->mm.mmrover;\r
+                       break;\r
+               case 2:\r
+                       MM_SortMem (gvar);\r
+                       lastscan = gvar->mm.mmhead;\r
+                       scan = gvar->mm.mmhead->next;\r
+                       endscan = NULL;\r
+                       break;\r
+               }\r
+\r
+               startseg = lastscan->start + lastscan->length;\r
+\r
+               while (scan != endscan)\r
+               {\r
+                       if (scan->start - startseg >= needed)\r
+                       {\r
+                       //\r
+                       // got enough space between the end of lastscan and\r
+                       // the start of scan, so throw out anything in the middle\r
+                       // and allocate the new block\r
+                       //\r
+                               purge = lastscan->next;\r
+                               lastscan->next = gvar->mm.mmnew;\r
+                               gvar->mm.mmnew->start = *(unsigned *)baseptr = startseg;\r
+                               gvar->mm.mmnew->next = scan;\r
+                               while ( purge != scan)\r
+                               {       // free the purgable block\r
+                                       next = purge->next;\r
+                                       FREEBLOCK(purge);\r
+                                       purge = next;           // purge another if not at scan\r
+                               }\r
+                               gvar->mm.mmrover = gvar->mm.mmnew;\r
+                               return; // good allocation!\r
+                       }\r
+\r
+                       //\r
+                       // if this block is purge level zero or locked, skip past it\r
+                       //\r
+                       if ( (scan->attributes & LOCKBIT)\r
+                               || !(scan->attributes & PURGEBITS) )\r
+                       {\r
+                               lastscan = scan;\r
+                               startseg = lastscan->start + lastscan->length;\r
+                       }\r
+\r
+\r
+                       scan=scan->next;                // look at next line\r
+               }\r
+       }\r
+\r
+       if (gvar->mm.bombonerror)\r
+       {\r
+#ifdef __WATCOMC__\r
+               //heapdump();\r
+#endif\r
+               printf(OUT_OF_MEM_MSG,(size-gvar->mmi.nearheap));\r
+               printf("for stability reasons the program will shut down! wwww\n");\r
+               MM_Shutdown(gvar);\r
+               exit(-1);\r
+       }\r
+       else\r
+               gvar->mm.mmerror = true;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= MM_FreePtr\r
+=\r
+= Allocates an unlocked, unpurgable block\r
+=\r
+====================\r
+*/\r
+\r
+void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *last;\r
+       mmblocktype far *scan,far *last;\r
+\r
+       last = gvar->mm.mmhead;\r
+       scan = last->next;\r
+\r
+       if(baseptr == gvar->mm.mmrover->useptr) // removed the last allocated block\r
+               gvar->mm.mmrover = gvar->mm.mmhead;\r
+\r
+       while(scan->useptr != baseptr && scan)\r
+       {\r
+               last = scan;\r
+               scan = scan->next;\r
+       }\r
+\r
+       if(!scan)\r
+       {\r
+               printf("MM_FreePtr: Block not found!\n");\r
+               return;\r
+       }\r
+\r
+       last->next = scan->next;\r
+\r
+       FREEBLOCK(scan);\r
+}\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_SetPurge\r
+=\r
+= Sets the purge level for a block (locked blocks cannot be made purgable)\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *start;\r
+       mmblocktype far *start;\r
+\r
+       start = gvar->mm.mmrover;\r
+\r
+       do\r
+       {\r
+               if(gvar->mm.mmrover->useptr == baseptr)\r
+                       break;\r
+\r
+               gvar->mm.mmrover = gvar->mm.mmrover->next;\r
+\r
+               if(!gvar->mm.mmrover)\r
+                       gvar->mm.mmrover = gvar->mm.mmhead;\r
+               else if(gvar->mm.mmrover == start)\r
+               {\r
+#ifdef __DEBUG_PM__\r
+                       printf("\nstart->useptr gvar->mm.mmhead->useptr\n");\r
+                       printf("        %Fp     %Fp\n", start->useptr, gvar->mm.mmhead->useptr);\r
+                       printf("&       %Fp     %Fp\n", &(start->useptr), &(gvar->mm.mmhead->useptr));\r
+                       printf("baseptr                 gvar->mm.mmrover->useptr\n");\r
+                       printf("        %Fp     %Fp\n", baseptr, gvar->mm.mmrover->useptr);\r
+                       printf("&       %Fp     %Fp\n", &(baseptr), &(gvar->mm.mmrover->useptr));\r
+                       printf("*       %Fp     %Fp\n", *(baseptr), *(gvar->mm.mmrover->useptr));\r
+                       printf("start                   gvar->mm.mmrover gvar->mm.mmrover->next\n");\r
+                       printf("        %Fp     %Fp     %Fp\n", start, gvar->mm.mmrover, gvar->mm.mmrover->next);\r
+                       printf("&       %Fp     %Fp     %Fp\n", &start, &gvar->mm.mmrover, gvar->mm.mmrover->next);\r
+                       getch();\r
+                       MM_ShowMemory(gvar);\r
+                       MM_DumpData(gvar);\r
+                       MM_Report_(gvar);\r
+                       getch();\r
+#endif\r
+                       Quit("MM_SetPurge: Block not found!");\r
+                       return;\r
+               }\r
+\r
+       } while(1);\r
+\r
+       gvar->mm.mmrover->attributes &= ~PURGEBITS;\r
+       gvar->mm.mmrover->attributes |= purge;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_SetLock\r
+=\r
+= Locks / unlocks the block\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *start;\r
+       mmblocktype far *start;\r
+\r
+       start = gvar->mm.mmrover;\r
+\r
+       do\r
+       {\r
+               if(gvar->mm.mmrover->useptr == baseptr)\r
+                       break;\r
+\r
+               gvar->mm.mmrover = gvar->mm.mmrover->next;\r
+\r
+               if(!gvar->mm.mmrover)\r
+                       gvar->mm.mmrover = gvar->mm.mmhead;\r
+               else if(gvar->mm.mmrover == start)\r
+               {\r
+                       Quit("MM_SetLock: Block not found!");\r
+                       //return;\r
+               }\r
+\r
+       } while(1);\r
+\r
+       gvar->mm.mmrover->attributes &= ~LOCKBIT;\r
+       gvar->mm.mmrover->attributes |= locked*LOCKBIT;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_SortMem\r
+=\r
+= Throws out all purgable stuff and compresses movable blocks\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_SortMem(global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *last,huge *next;\r
+       mmblocktype far *scan,far *last,far *next;\r
+       unsigned        start,length,source,dest,oldborder;\r
+       int                     playing;\r
+\r
+       //\r
+       // lock down a currently playing sound\r
+       //\r
+/*++++ playing = SD_SoundPlaying ();\r
+       if(playing)\r
+       {\r
+               switch (SoundMode)\r
+               {\r
+               case sdm_PC:\r
+                       playing += STARTPCSOUNDS;\r
+                       break;\r
+               case sdm_AdLib:\r
+                       playing += STARTADLIBSOUNDS;\r
+                       break;\r
+               }\r
+               MM_SetLock(&(memptr)audiosegs[playing],true);\r
+       }\r
+\r
+\r
+       SD_StopSound();*/\r
+//     oldborder = bordercolor;\r
+//     VW_ColorBorder (15);\r
+\r
+       if(beforesort)\r
+               beforesort();\r
+\r
+       scan = gvar->mm.mmhead;\r
+\r
+       last = NULL;            // shut up compiler warning\r
+\r
+       while(scan)\r
+       {\r
+               if(scan->attributes & LOCKBIT)\r
+               {\r
+               //\r
+               // block is locked, so try to pile later blocks right after it\r
+               //\r
+                       start = scan->start + scan->length;\r
+               }\r
+               else\r
+               {\r
+                       if(scan->attributes & PURGEBITS)\r
+                       {\r
+                       //\r
+                       // throw out the purgable block\r
+                       //\r
+                               next = scan->next;\r
+                               FREEBLOCK(scan);\r
+                               //MM_FreeBlock(scan, gvar);\r
+                               last->next = next;\r
+                               scan = next;\r
+                               continue;\r
+                       }\r
+                       else\r
+                       {\r
+                       //\r
+                       // push the non purgable block on top of the last moved block\r
+                       //\r
+                               if(scan->start != start)\r
+                               {\r
+                                       length = scan->length;\r
+                                       source = scan->start;\r
+                                       dest = start;\r
+                                       while(length > 0xf00)\r
+                                       {\r
+                                               movedata(source,0,dest,0,0xf00*16);\r
+                                               length -= 0xf00;\r
+                                               source += 0xf00;\r
+                                               dest += 0xf00;\r
+                                       }\r
+                                       movedata(source,0,dest,0,length*16);\r
+\r
+                                       scan->start = start;\r
+                                       *(unsigned *)scan->useptr = start;\r
+                               }\r
+                               start = scan->start + scan->length;\r
+                       }\r
+               }\r
+\r
+               last = scan;\r
+               scan = scan->next;              // go to next block\r
+       }\r
+\r
+       gvar->mm.mmrover = gvar->mm.mmhead;\r
+\r
+       if(aftersort)\r
+               aftersort();\r
+\r
+//     VW_ColorBorder (oldborder);\r
+\r
+/*++++ if(playing)\r
+               MM_SetLock(&(memptr)audiosegs[playing],false);*/\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_ShowMemory\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_ShowMemory(global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan;\r
+       mmblocktype far *scan;\r
+       word temp;\r
+       sdword  end,owner;\r
+       //word chx,chy;\r
+       word w;\r
+       //dword wwww;\r
+       byte    scratch[160],scratch0[4096],scratch1[160],str[16];\r
+       //byte d = '#';\r
+//**** VW_SetDefaultColors();\r
+//**** VW_SetLineWidth(40);\r
+//++++mh       temp = bufferofs;\r
+//++++mh       bufferofs = 0;\r
+//**** VW_SetScreen (0,0);\r
+       scan = gvar->mm.mmhead;\r
+       end = -1;\r
+\r
+       CA_OpenDebug (gvar);\r
+       w=0;\r
+       while(scan)\r
+       {\r
+               strcpy(scratch, AARESET);\r
+               if(scan->attributes & PURGEBITS)\r
+                       strcpy(scratch0, AAMAGENTA);            // dark purple = purgable\r
+               else\r
+                       strcpy(scratch0, AABLUE);               // medium blue = non purgable\r
+               if(scan->attributes & LOCKBIT)\r
+                       strcpy(scratch0, AARED);                // red = locked\r
+               if(scan->start<=end)\r
+               {\r
+                       printf("\nend==%d\n\n", end);\r
+                       strcat(scratch, "MM_ShowMemory: Memory block order currupted!\n");\r
+                       strcat(scratch, "End's Size: ");\r
+                       ultoa (end,str,10);\r
+                       strcat (scratch,str);\r
+                       strcat(scratch, "\nscan->start's Size: ");\r
+                       ultoa (scan->start,str,10);\r
+                       strcat (scratch,str);\r
+                       write(gvar->handle.debughandle,scratch,strlen(scratch));\r
+                       //modexprint(&page, chx, chy, 1, 0, 24, "\nMM_ShowMemory: Memory block order currupted!\n");\r
+                       break;\r
+               }\r
+               end = scan->start+(scan->length)-1;\r
+//++++         chy = scan->start/320;\r
+//++++         chx = scan->start%320;\r
+                               //modexhlin(page, scan->start, (unsigned)end, chy, color);\r
+                               //for(chx=scan->start;chx+4>=(word)end;chx+=4)\r
+                               //{\r
+//++++                                 modexClearRegion(page, chx, chy, 4, 4, color);\r
+                               //}\r
+//++++         VW_Hlin(scan->start,(unsigned)end,0,color);\r
+               for(w=(scan->start)/80;w<=end/80;w++)\r
+               {\r
+                       //printf("+     %u      %lu\n", w, scan->length);\r
+                       strcat(scratch0, "+");\r
+               }\r
+               //++==++==optional strcat(scratch0, AARESET); strcat(scratch0, AAGREY); strcat(scratch0,"_");\r
+//++++         VW_Plot(scan->start,0,15);\r
+//++++                         modexClearRegion(page, chx, chy, 4, 4, 15);\r
+//++++                 VW_Hlin(end+1,scan->next->start,0,0);   // black = free\r
+\r
+               //wwww=(dword)(scan->next->start)-(dword)scan->start;\r
+               //wwww=(dword)scan->start+(dword)(scan->next->start);\r
+               if (scan->next && scan->next->start >= end+1)\r
+               {\r
+                       strcat(scratch0, AARESET);\r
+                       //++==++==optional strcat(scratch0, "\n");\r
+                       strcat(scratch0,AAGREEN);\r
+                       for(w=(end+1)/80;w<=((scan->next->start-scan->start)/80);w++)\r
+                       //for(w=(wwww)/80;w<=((end+1)/80);w++)\r
+                       //for(w=(end+1)/80;w<=((wwww)/80);w++)\r
+                       {\r
+                               //printf("0     %x      %u      %lu\n", scan->next->start, w, scan->length);\r
+                               strcat(scratch0,"0");\r
+                       }\r
+                       //printf("==================\n");\r
+                       //printf("w=%u  wwww=%lu        start=%04x      next=%04x       end=%lu\n", w/80, wwww/80, scan->start, (scan->next->start), end+1);\r
+                       //printf("==================\n");\r
+                       strcat(scratch0, "\n");\r
+                       //getch();\r
+               }/*else {//if(scan->next->start <= scan->start){\r
+                       scan->next->start=scan->start+0x1000;\r
+                       wwww=(dword)(scan->next->start)-(dword)scan->start;\r
+                       strcat(scratch0, AARESET);\r
+                       strcat(scratch0, "\n");\r
+                       strcat(scratch0,AAGREEN);\r
+                       for(w=(end+1);w<=(0x1000/80);w++)\r
+                       {\r
+                               //printf("0     %x      %x      %u\n", scan->start, w);\r
+                               strcat(scratch0,"0");\r
+                       }\r
+                       printf("================\n");\r
+                       printf("w=%x    start=%x        next=%x end=%u  %lu\n", w, scan->start, (scan->next->start), end+1, wwww);\r
+                       printf("================\n");\r
+                       getch();\r
+               }*/\r
+               strcat(scratch0, AARESET);\r
+               //strcat(scratch0,"\n");\r
+                       //for(chx=scan->next->start;chx+4>=(word)end+1;chx+=4)\r
+                       //{\r
+//                             chx+=scan->next->start;\r
+//                             modexClearRegion(page, chx, chy, 4, 4, 2);\r
+                       //}\r
+                                       //modexhlin(page, end+1,scan->next->start, chy, 0);\r
+/*             y = scan->start/320;\r
+               x = scan->start%320;\r
+               VW_Hlin(x,x+end,y,color);\r
+               VW_Plot(x,y,15);*/\r
+//++++                 VW_Hlin(x+end+1,x+(scan->next->start-scan->start),y,0); // black = free\r
+               strcat(scratch,"Seg:");\r
+               ultoa (scan->start,str,16);\r
+               strcat (scratch,str);\r
+               strcat (scratch,"\tSize:");\r
+               ultoa ((unsigned)scan->length,str,10);\r
+               strcat (scratch,str);\r
+               strcat (scratch,"\tOwner:0x");\r
+               owner = (unsigned)scan->useptr;\r
+               ultoa (owner,str,16);\r
+               strcat (scratch,str);\r
+               strcat (scratch,"\n");\r
+               write(gvar->handle.debughandle,scratch,strlen(scratch));\r
+               write(gvar->handle.debughandle,scratch0,strlen(scratch0));\r
+//modexprint(page, chx, chy, 1, 0, 24, &scratch);\r
+//++++chy+=4;\r
+//fprintf(stdout, "%s", scratch);\r
+\r
+               scan = scan->next;\r
+       }\r
+       /*strcpy(scratch1, AARESET);\r
+       strcat(scratch1, "========================================\n");\r
+       strcat(scratch1, "near=  ");\r
+       ultoa (*(gvar->mm.nearheap),str,10);\r
+       strcat (scratch1,str);\r
+       strcat(scratch1, "      far= ");\r
+       ultoa (*(gvar->mm.farheap),str,10);\r
+       strcat (scratch1,str);\r
+       strcat(scratch1, "\n");\r
+       //strcat(scratch1, "&near=      %Fp ", &(gvar->mm.nearheap));\r
+       //strcat(scratch1, "&far=       %Fp", &(gvar->mm.farheap));\r
+       //strcat(scratch1, "\n");\r
+       strcat(scratch1, "========================================\n");\r
+       write(gvar->handle.debughandle,scratch1,strlen(scratch1));*/\r
+\r
+\r
+       CA_CloseDebug (gvar);\r
+\r
+//++++mh       IN_Ack();\r
+//**** VW_SetLineWidth(64);\r
+//++++mh       bufferofs = temp;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_DumpData\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_DumpData(global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *best;\r
+       mmblocktype far *scan,far *best;\r
+       long    lowest,oldlowest;\r
+       word    owner;\r
+       byte    lock,purge;\r
+       FILE    *dumpfile;\r
+\r
+       free(gvar->mm.nearheap);\r
+#ifdef __BORLANDC__\r
+               dumpfile = fopen ("mmdump.16b","w");\r
+#endif\r
+#ifdef __WATCOMC__\r
+               dumpfile = fopen ("mmdump.16w","w");\r
+#endif\r
+       if (!dumpfile){\r
+               printf("MM_DumpData: Couldn't open MMDUMP.16!\n");\r
+               return;\r
+       }\r
+\r
+       lowest = -1;\r
+       do\r
+       {\r
+               oldlowest = lowest;\r
+               lowest = 0xffff;\r
+\r
+               scan = gvar->mm.mmhead;\r
+               while (scan)\r
+               {\r
+                       owner = (unsigned)scan->useptr;\r
+\r
+                       if (owner && owner<lowest && owner > oldlowest)\r
+                       {\r
+                               best = scan;\r
+                               lowest = owner;\r
+                       }\r
+\r
+                       scan = scan->next;\r
+               }\r
+\r
+               if (lowest != 0xffff)\r
+               {\r
+                       if (best->attributes & PURGEBITS)\r
+                               purge = 'P';\r
+                       else\r
+                               purge = '-';\r
+                       if (best->attributes & LOCKBIT)\r
+                               lock = 'L';\r
+                       else\r
+                               lock = '-';\r
+                       fprintf (dumpfile,"0x%p (%c%c) = %u\n"\r
+                       ,(unsigned)lowest,lock,purge,best->length);\r
+               }\r
+\r
+       } while (lowest != 0xffff);\r
+\r
+       fclose(dumpfile);\r
+       printf("MMDUMP.16 created.\n");\r
+}\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MM_UnusedMemory\r
+=\r
+= Returns the total free space without purging\r
+=\r
+======================\r
+*/\r
+\r
+dword MM_UnusedMemory(global_game_variables_t *gvar)\r
+{\r
+       dword free;\r
+       //huge mmblocktype huge *scan;\r
+       mmblocktype far *scan;\r
+\r
+       free = 0;\r
+       scan = gvar->mm.mmhead;\r
+\r
+       while(scan->next)\r
+       {\r
+               free += scan->next->start - (scan->start + scan->length);\r
+               scan = scan->next;\r
+       }\r
+\r
+       return free*16lu;\r
+//     return free;\r
+}\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MM_TotalFree\r
+=\r
+= Returns the total free space with purging\r
+=\r
+======================\r
+*/\r
+\r
+dword MM_TotalFree(global_game_variables_t *gvar)\r
+{\r
+       dword free;\r
+       //huge mmblocktype huge *scan;\r
+       mmblocktype far *scan;\r
+\r
+       free = 0;\r
+       scan = gvar->mm.mmhead;\r
+\r
+       while(scan->next)\r
+       {\r
+               if((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT))\r
+                       free += scan->length;\r
+               free += scan->next->start - (scan->start + scan->length);\r
+               scan = scan->next;\r
+       }\r
+\r
+       return free*16lu;\r
+//     return free;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_Report\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_Report_(global_game_variables_t *gvar)\r
+{\r
+       printf("========================================\n");\r
+       printf("                MM_Report\n");\r
+       printf("========================================\n");\r
+       if(MML_CheckForEMS())\r
+       {\r
+               printf("        LIMEMS\n");\r
+               printf("                EMM v%x.%x available\n", gvar->pm.emm.EMSVer>>4,gvar->pm.emm.EMSVer&0x0F);\r
+               printf("                totalEMSpages:  %u      ", gvar->pm.emm.totalEMSpages); printf("freeEMSpages:   %u\n", gvar->pm.emm.freeEMSpages);\r
+               printf("                EMSPageFrame:   %x\n", gvar->pm.emm.EMSPageFrame);\r
+       }\r
+       if(MML_CheckForXMS(gvar))\r
+       {\r
+               printf("        XMS\n");\r
+               printf("                XMSaddr:        %X\n", *XMSaddr);\r
+       }\r
+       printf("near:   %lu     ", gvar->mmi.nearheap); printf("far:    %lu\n", gvar->mmi.farheap); if(MML_CheckForEMS())\r
+       printf("EMSmem: %lu     ", gvar->mmi.EMSmem); if(MML_CheckForXMS(gvar)) printf("XMSmem: %lu", gvar->mmi.XMSmem); printf("\n");\r
+       //printf("mainmem:      %lu\n", gvar->mmi.mainmem);\r
+       printf("Total convmem:  %lu     ", gvar->mmi.mainmem); printf("TotalFree:       %lu     ", MM_TotalFree(gvar)); printf("TotalUsed:      %lu\n", gvar->mmi.mainmem+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem);\r
+       printf("                        UnusedMemory:   %lu\n", MM_UnusedMemory(gvar));\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_EMSerr\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_EMSerr(byte *stri, byte err)\r
+{\r
+       //Returns a text string describing the error code in EMS.Error.\r
+       switch(err)\r
+       {\r
+               case 0x0:\r
+                       strcat(stri, "successful");\r
+               break;\r
+               case 0x80:\r
+                       strcat(stri, "internal error");\r
+               break;\r
+               case 0x81:\r
+                       strcat(stri, "hardware malfunction");\r
+               break;\r
+               case 0x82:\r
+                       strcat(stri, "busy .. retry later");\r
+               break;\r
+               case 0x83:\r
+                       strcat(stri, "invalid handle");\r
+               break;\r
+               case 0x84:\r
+                       strcat(stri, "undefined function requested by application");\r
+               break;\r
+               case 0x85:\r
+                       strcat(stri, "no more handles available");\r
+               break;\r
+               case 0x86:\r
+                       strcat(stri, "error in save or restore of mapping context");\r
+               break;\r
+               case 0x87:\r
+                       strcat(stri, "insufficient memory pages in system");\r
+               break;\r
+               case 0x88:\r
+                       strcat(stri, "insufficient memory pages available");\r
+               break;\r
+               case 0x89:\r
+                       strcat(stri, "zero pages requested");\r
+               break;\r
+               case 0x8A:\r
+                       strcat(stri, "invalid logical page number encountered");\r
+               break;\r
+               case 0x8B:\r
+                       strcat(stri, "invalid physical page number encountered");\r
+               break;\r
+               case 0x8C:\r
+                       strcat(stri, "page-mapping hardware state save area is full");\r
+               break;\r
+               case 0x8D:\r
+                       strcat(stri, "save of mapping context failed");\r
+               break;\r
+               case 0x8E:\r
+                       strcat(stri, "restore of mapping context failed");\r
+               break;\r
+               case 0x8F:\r
+                       strcat(stri, "undefined subfunction");\r
+               break;\r
+               case 0x90:\r
+                       strcat(stri, "undefined attribute type");\r
+               break;\r
+               case 0x91:\r
+                       strcat(stri, "feature not supported");\r
+               break;\r
+               case 0x92:\r
+                       strcat(stri, "successful, but a portion of the source region has been overwritten");\r
+               break;\r
+               case 0x93:\r
+                       strcat(stri, "length of source or destination region exceeds length of region allocated to either source or destination handle");\r
+               break;\r
+               case 0x94:\r
+                       strcat(stri, "conventional and expanded memory regions overlap");\r
+               break;\r
+               case 0x95:\r
+                       strcat(stri, "offset within logical page exceeds size of logical page");\r
+               break;\r
+               case 0x96:\r
+                       strcat(stri, "region length exceeds 1 MB");\r
+               break;\r
+               case 0x97:\r
+                       strcat(stri, "source and destination EMS regions have same handle and overlap");\r
+               break;\r
+               case 0x98:\r
+                       strcat(stri, "memory source or destination type undefined");\r
+               break;\r
+               case 0x9A:\r
+                       strcat(stri, "specified alternate map register or DMA register set not supported");\r
+               break;\r
+               case 0x9B:\r
+                       strcat(stri, "all alternate map register or DMA register sets currently allocated");\r
+               break;\r
+               case 0x9C:\r
+                       strcat(stri, "alternate map register or DMA register sets not supported");\r
+               break;\r
+               case 0x9D:\r
+                       strcat(stri, "undefined or unallocated alternate map register or DMA register set");\r
+               break;\r
+               case 0x9E:\r
+                       strcat(stri, "dedicated DMA channels not supported");\r
+               break;\r
+               case 0x9F:\r
+                       strcat(stri, "specified dedicated DMA channel not supported");\r
+               break;\r
+               case 0xA0:\r
+                       strcat(stri, "no such handle name");\r
+               break;\r
+               case 0xA1:\r
+                       strcat(stri, "a handle found had no name, or duplicate handle name");\r
+               break;\r
+               case 0xA2:\r
+                       strcat(stri, "attempted to wrap around 1M conventional address space");\r
+               break;\r
+               case 0xA3:\r
+                       strcat(stri, "source array corrupted");\r
+               break;\r
+               case 0xA4:\r
+                       strcat(stri, "operating system denied access");\r
+               break;\r
+               default:\r
+                       strcat(stri, "undefined error");\r
+       }\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_BombOnError\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_BombOnError(boolean bomb, global_game_variables_t *gvar)\r
+{\r
+       gvar->mm.bombonerror = bomb;\r
+}\r
+\r
+/*void MM_GetNewBlock(global_game_variables_t *gvar)\r
+{\r
+       if(!gvar->mm.mmfree)\r
+               MML_ClearBlock(gvar);\r
+       gvar->mm.mmnew=gvar->mm.mmfree;\r
+       gvar->mm.mmfree=gvar->mm.mmfree->next;\r
+       if(!(gvar->mm.mmnew=gvar->mm.mmfree))\r
+       {\r
+               printf("MM_GETNEWBLOCK: No free blocks!\n");\r
+               return;\r
+       }\r
+       gvar->mm.mmfree=gvar->mm.mmfree->next;\r
+}\r
+\r
+void MM_FreeBlock(mmblocktype *x, global_game_variables_t *gvar)\r
+{\r
+       x->useptr=NULL;\r
+       x->next=gvar->mm.mmfree;\r
+       gvar->mm.mmfree=x;\r
+}*/\r
+\r
+/*void MM_seguin(void)\r
+{\r
+       __asm {\r
+               push    ds\r
+               mov     ax,ds\r
+               inc             ax\r
+               mov     ds,ax\r
+       }\r
+}\r
+\r
+void MM_segude(void)\r
+{\r
+       __asm {\r
+               pop ds\r
+       }\r
+}*/\r
+\r
+/*\r
+pull data from far and put it into ds var\r
+mov ax,es:si\r
+mov x,ax\r
+*/\r
+/*\r
+ss stack segment\r
+sp top of stack\r
+bp bottem of stack\r
+*/\r
index 546573cb6951109cb3bf1aa6b804f95cbe215df2..c7bd7809fca69d6543baee560e6ce4d0a7585743 100755 (executable)
--- a/DEBUG.16B
+++ b/DEBUG.16B
-\e[0mSeg:0      Size:2982       Owner:0x6574\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m0\r
-\e[0m\e[0mSeg:ba6        Size:256        Owner:0xcf7a\r
+\e[0mSeg:0      Size:5151       Owner:0x0\r
+\e[41;31m+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m0\r
+\e[0m\e[0mSeg:141f       Size:256        Owner:0xed5\r
 \e[44;34m++++\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:ca6        Size:273        Owner:0xfde\r
-\e[44;34m++++\e[0m\e[42;32m000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-\e[0m\e[0mSeg:9fde       Size:28706      Owner:0x0\r
+\e[0m\e[0mSeg:151f       Size:256        Owner:0xcd6\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:161f       Size:256        Owner:0xcd8\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:171f       Size:256        Owner:0xcda\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:181f       Size:256        Owner:0xcdc\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:191f       Size:256        Owner:0xcde\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:1a1f       Size:256        Owner:0xce0\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:1b1f       Size:256        Owner:0xce2\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:1c1f       Size:256        Owner:0xce4\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:1d1f       Size:256        Owner:0xce6\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:1e1f       Size:256        Owner:0xce8\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:1f1f       Size:256        Owner:0xcea\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:201f       Size:256        Owner:0xcec\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:211f       Size:256        Owner:0xcee\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:221f       Size:256        Owner:0xcf0\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:231f       Size:256        Owner:0xcf2\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:241f       Size:256        Owner:0xcf4\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:251f       Size:256        Owner:0xcf6\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:261f       Size:256        Owner:0xcf8\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:271f       Size:256        Owner:0xcfa\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:281f       Size:256        Owner:0xcfc\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:291f       Size:256        Owner:0xcfe\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:2a1f       Size:256        Owner:0xd00\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:2b1f       Size:256        Owner:0xd02\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:2c1f       Size:256        Owner:0xd04\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:2d1f       Size:256        Owner:0xd06\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:2e1f       Size:256        Owner:0xd08\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:2f1f       Size:256        Owner:0xd0a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:301f       Size:256        Owner:0xd0c\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:311f       Size:256        Owner:0xd0e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:321f       Size:256        Owner:0xd10\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:331f       Size:256        Owner:0xd12\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:341f       Size:256        Owner:0xd14\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:351f       Size:256        Owner:0xd16\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:361f       Size:256        Owner:0xd18\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:371f       Size:256        Owner:0xd1a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:381f       Size:256        Owner:0xd1c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:391f       Size:256        Owner:0xd1e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3a1f       Size:256        Owner:0xd20\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3b1f       Size:256        Owner:0xd22\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3c1f       Size:256        Owner:0xd24\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3d1f       Size:256        Owner:0xd26\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3e1f       Size:256        Owner:0xd28\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3f1f       Size:256        Owner:0xd2a\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:401f       Size:256        Owner:0xd2c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:411f       Size:256        Owner:0xd2e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:421f       Size:256        Owner:0xd30\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:431f       Size:256        Owner:0xd32\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:441f       Size:256        Owner:0xd34\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:451f       Size:256        Owner:0xd36\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:461f       Size:256        Owner:0xd38\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:471f       Size:256        Owner:0xd3a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:481f       Size:256        Owner:0xd3c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:491f       Size:256        Owner:0xd3e\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4a1f       Size:256        Owner:0xd40\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4b1f       Size:256        Owner:0xd42\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4c1f       Size:256        Owner:0xd44\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4d1f       Size:256        Owner:0xd46\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4e1f       Size:256        Owner:0xd48\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4f1f       Size:256        Owner:0xd4a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:501f       Size:256        Owner:0xd4c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:511f       Size:256        Owner:0xd4e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:521f       Size:256        Owner:0xd50\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:531f       Size:256        Owner:0xd52\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:541f       Size:256        Owner:0xd54\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:551f       Size:256        Owner:0xd56\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:561f       Size:256        Owner:0xd58\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:571f       Size:256        Owner:0xd5a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:581f       Size:256        Owner:0xd5c\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:591f       Size:256        Owner:0xd5e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5a1f       Size:256        Owner:0xd60\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5b1f       Size:256        Owner:0xd62\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5c1f       Size:256        Owner:0xd64\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5d1f       Size:256        Owner:0xd66\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5e1f       Size:256        Owner:0xd68\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5f1f       Size:256        Owner:0xd6a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:601f       Size:256        Owner:0xd6c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:611f       Size:256        Owner:0xd6e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:621f       Size:256        Owner:0xd70\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:631f       Size:256        Owner:0xd72\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:641f       Size:256        Owner:0xd74\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:651f       Size:256        Owner:0xd76\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:661f       Size:256        Owner:0xd78\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:671f       Size:256        Owner:0xd7a\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:681f       Size:256        Owner:0xd7c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:691f       Size:256        Owner:0xd7e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6a1f       Size:256        Owner:0xd80\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6b1f       Size:256        Owner:0xd82\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6c1f       Size:256        Owner:0xd84\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6d1f       Size:256        Owner:0xd86\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6e1f       Size:256        Owner:0xd88\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6f1f       Size:256        Owner:0xd8a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:701f       Size:256        Owner:0xd8c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:711f       Size:256        Owner:0xd8e\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:721f       Size:256        Owner:0xd90\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:731f       Size:256        Owner:0xd92\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:741f       Size:256        Owner:0xd94\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:751f       Size:256        Owner:0xd96\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:761f       Size:256        Owner:0xd98\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:771f       Size:256        Owner:0xd9a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:781f       Size:256        Owner:0xd9c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:791f       Size:273        Owner:0xfde\r
+\e[44;34m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:9fde       Size:32802      Owner:0x0\r
 \e[41;31m\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:9ffe       Size:16386      Owner:0x0\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:e000       Size:8191       Owner:0x0\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m
\ No newline at end of file
+\e[0m\e[0mSeg:9ffe       Size:24577      Owner:0x0\r
+\e[41;31m+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m
\ No newline at end of file
index 8f3ffe4d29cb8c418ba1844872b735e9530f1d6f..86023db0db6ee704d19335b31dab4df8ca92fef5 100755 (executable)
--- a/DEBUG.16W
+++ b/DEBUG.16W
-\e[0mSeg:0      Size:7812       Owner:0x6568\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m0\r
-\e[0m\e[0mSeg:1e84       Size:256        Owner:0x5274\r
-\e[44;34m++++\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:1f84       Size:273        Owner:0x92cc\r
+\e[0mSeg:0      Size:11821      Owner:0x0\r
+\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m000\r
+\e[0m\e[0mSeg:2eb4       Size:37 Owner:0x0\r
+\e[41;31m+\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:2ed9       Size:256        Owner:0x1784\r
 \e[44;34m+++++\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:2513       Size:44 Owner:0x0\r
-\e[41;31m++\e[0m\e[42;32m0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-\e[0m\e[0mSeg:b53f       Size:10945      Owner:0x0\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:e000       Size:8191       Owner:0x0\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m
\ No newline at end of file
+\e[0m\e[0mSeg:2fd9       Size:256        Owner:0x1572\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:30d9       Size:256        Owner:0x1574\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:31d9       Size:256        Owner:0x1576\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:32d9       Size:256        Owner:0x1578\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:33d9       Size:256        Owner:0x157a\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:34d9       Size:256        Owner:0x157c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:35d9       Size:256        Owner:0x157e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:36d9       Size:256        Owner:0x1580\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:37d9       Size:256        Owner:0x1582\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:38d9       Size:256        Owner:0x1584\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:39d9       Size:256        Owner:0x1586\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3ad9       Size:256        Owner:0x1588\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3bd9       Size:256        Owner:0x158a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3cd9       Size:256        Owner:0x158c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3dd9       Size:256        Owner:0x158e\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3ed9       Size:256        Owner:0x1590\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:3fd9       Size:256        Owner:0x1592\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:40d9       Size:256        Owner:0x1594\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:41d9       Size:256        Owner:0x1596\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:42d9       Size:256        Owner:0x1598\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:43d9       Size:256        Owner:0x159a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:44d9       Size:256        Owner:0x159c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:45d9       Size:256        Owner:0x159e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:46d9       Size:256        Owner:0x15a0\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:47d9       Size:256        Owner:0x15a2\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:48d9       Size:256        Owner:0x15a4\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:49d9       Size:256        Owner:0x15a6\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4ad9       Size:256        Owner:0x15a8\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4bd9       Size:256        Owner:0x15aa\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4cd9       Size:256        Owner:0x15ac\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4dd9       Size:256        Owner:0x15ae\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4ed9       Size:256        Owner:0x15b0\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:4fd9       Size:256        Owner:0x15b2\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:50d9       Size:256        Owner:0x15b4\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:51d9       Size:256        Owner:0x15b6\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:52d9       Size:256        Owner:0x15b8\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:53d9       Size:256        Owner:0x15ba\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:54d9       Size:256        Owner:0x15bc\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:55d9       Size:256        Owner:0x15be\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:56d9       Size:256        Owner:0x15c0\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:57d9       Size:256        Owner:0x15c2\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:58d9       Size:256        Owner:0x15c4\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:59d9       Size:256        Owner:0x15c6\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5ad9       Size:256        Owner:0x15c8\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5bd9       Size:256        Owner:0x15ca\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5cd9       Size:256        Owner:0x15cc\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5dd9       Size:256        Owner:0x15ce\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5ed9       Size:256        Owner:0x15d0\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:5fd9       Size:256        Owner:0x15d2\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:60d9       Size:256        Owner:0x15d4\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:61d9       Size:256        Owner:0x15d6\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:62d9       Size:256        Owner:0x15d8\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:63d9       Size:256        Owner:0x15da\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:64d9       Size:256        Owner:0x15dc\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:65d9       Size:256        Owner:0x15de\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:66d9       Size:256        Owner:0x15e0\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:67d9       Size:256        Owner:0x15e2\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:68d9       Size:256        Owner:0x15e4\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:69d9       Size:256        Owner:0x15e6\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6ad9       Size:256        Owner:0x15e8\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6bd9       Size:256        Owner:0x15ea\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6cd9       Size:256        Owner:0x15ec\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6dd9       Size:256        Owner:0x15ee\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6ed9       Size:256        Owner:0x15f0\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:6fd9       Size:256        Owner:0x15f2\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:70d9       Size:256        Owner:0x15f4\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:71d9       Size:256        Owner:0x15f6\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:72d9       Size:256        Owner:0x15f8\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:73d9       Size:256        Owner:0x15fa\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:74d9       Size:256        Owner:0x15fc\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:75d9       Size:256        Owner:0x15fe\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:76d9       Size:256        Owner:0x1600\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:77d9       Size:256        Owner:0x1602\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:78d9       Size:256        Owner:0x1604\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:79d9       Size:256        Owner:0x1606\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:7ad9       Size:256        Owner:0x1608\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:7bd9       Size:256        Owner:0x160a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:7cd9       Size:256        Owner:0x160c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:7dd9       Size:256        Owner:0x160e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:7ed9       Size:256        Owner:0x1610\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:7fd9       Size:256        Owner:0x1612\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:80d9       Size:256        Owner:0x1614\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:81d9       Size:256        Owner:0x1616\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:82d9       Size:256        Owner:0x1618\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:83d9       Size:256        Owner:0x161a\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:84d9       Size:256        Owner:0x161c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:85d9       Size:256        Owner:0x161e\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:86d9       Size:256        Owner:0x1620\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:87d9       Size:256        Owner:0x1622\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:88d9       Size:256        Owner:0x1624\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:89d9       Size:256        Owner:0x1626\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:8ad9       Size:256        Owner:0x1628\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:8bd9       Size:256        Owner:0x162a\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:8cd9       Size:256        Owner:0x162c\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:8dd9       Size:256        Owner:0x162e\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:8ed9       Size:256        Owner:0x1630\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:8fd9       Size:256        Owner:0x1632\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:90d9       Size:256        Owner:0x1634\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:91d9       Size:256        Owner:0x1636\r
+\e[45;35m++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:92d9       Size:256        Owner:0x1638\r
+\e[45;35m+++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:93d9       Size:401        Owner:0xf25a\r
+\e[44;34m++++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:bed9       Size:16678      Owner:0x0\r
+\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m
\ No newline at end of file
diff --git a/DEBUG_.16W b/DEBUG_.16W
deleted file mode 100755 (executable)
index e5d8c2f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-\e[0mSeg:0      Size:7705       Owner:0x0\r
-\e[41;31m+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[47;37m_\e[0m\r
-\e[42;32m0\r
-\e[0m\e[0mSeg:1e19       Size:256        Owner:0x527c\r
-\e[44;34m++++\e[0m\e[47;37m_\e[0m\r
-\e[42;32m\r
-\e[0m\e[0mSeg:1f19       Size:273        Owner:0x92d4\r
-\e[44;34m++++\e[0m\e[47;37m_\e[0m\r
-\e[42;32m\r
-\e[0m\e[0mSeg:24a8       Size:40 Owner:0x0\r
-\e[41;31m+\e[0m\e[47;37m_\e[0m\r
-\e[42;32m000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-\e[0m\e[0mSeg:b4d0       Size:11056      Owner:0x0\r
-\e[41;31m+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[47;37m_\e[0m\r
-\e[42;32m\r
-\e[0m\e[0mSeg:e000       Size:8191       Owner:0x0\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[47;37m_\e[0m
\ No newline at end of file
index d873f507e3c79368d13ee05dbef91d9f6c554821..0526b3209da0365c8de17c3e5929a57e7e6f3c39 100755 (executable)
--- a/HEAP.16W
+++ b/HEAP.16W
@@ -1,47 +1,71 @@
 \r
        == default ==\r
 \r
-  USED block at 25350016 of size 66\r
-  USED block at 25350058 of size 66\r
-  FREE block at 2535009a of size 18\r
-  USED block at 253500ac of size 136\r
-  USED block at 25350134 of size 20\r
-  FREE block at 25350148 of size 7860\r
+  FREE block at 2ed70016 of size 18\r
+  USED block at 2ed70028 of size 50\r
+  USED block at 2ed7005a of size 50\r
+  USED block at 2ed7008c of size 50\r
+  USED block at 2ed700be of size 50\r
+  USED block at 2ed700f0 of size 50\r
+  USED block at 2ed70122 of size 50\r
+  USED block at 2ed70154 of size 50\r
+  USED block at 2ed70186 of size 50\r
+  USED block at 2ed701b8 of size 50\r
+  USED block at 2ed701ea of size 50\r
+  USED block at 2ed7021c of size 50\r
+  USED block at 2ed7024e of size 50\r
+  USED block at 2ed70280 of size 50\r
+  FREE block at 2ed702b2 of size 14\r
+  USED block at 2ed702c0 of size 20\r
+  USED block at 2ed702d4 of size 136\r
+  FREE block at 2ed7035c of size 7328\r
 OK - end of heap\r
 \r
        == near ==\r
 \r
-  USED block at 15349306 of size 12\r
-  USED block at 15349312 of size 332\r
-  USED block at 1534945e of size 52\r
-  USED block at 15349492 of size 20\r
-  USED block at 153494a6 of size 20\r
-  USED block at 153494ba of size 20\r
-  USED block at 153494ce of size 20\r
-  USED block at 153494e2 of size 20\r
-  USED block at 153494f6 of size 27398\r
+  USED block at 1ed6f2a6 of size 12\r
+  USED block at 1ed6f2b2 of size 528\r
+  USED block at 1ed6f4c2 of size 72\r
+  USED block at 1ed6f50a of size 20\r
+  USED block at 1ed6f51e of size 20\r
+  USED block at 1ed6f532 of size 20\r
+  USED block at 1ed6f546 of size 20\r
+  USED block at 1ed6f55a of size 20\r
+  USED block at 1ed6f56e of size 2702\r
 OK - end of heap\r
 \r
        == far ==\r
 \r
-  USED block at 25350016 of size 66\r
-  USED block at 25350058 of size 66\r
-  USED block at 2535009a of size 18\r
-  USED block at 253500ac of size 136\r
-  USED block at 25350134 of size 20\r
-  USED block at 25350148 of size 7860\r
+  USED block at 2ed70016 of size 18\r
+  USED block at 2ed70028 of size 50\r
+  USED block at 2ed7005a of size 50\r
+  USED block at 2ed7008c of size 50\r
+  USED block at 2ed700be of size 50\r
+  USED block at 2ed700f0 of size 50\r
+  USED block at 2ed70122 of size 50\r
+  USED block at 2ed70154 of size 50\r
+  USED block at 2ed70186 of size 50\r
+  USED block at 2ed701b8 of size 50\r
+  USED block at 2ed701ea of size 50\r
+  USED block at 2ed7021c of size 50\r
+  USED block at 2ed7024e of size 50\r
+  USED block at 2ed70280 of size 50\r
+  USED block at 2ed702b2 of size 14\r
+  USED block at 2ed702c0 of size 20\r
+  USED block at 2ed702d4 of size 136\r
+  USED block at 2ed7035c of size 7328\r
 OK - end of heap\r
 \r
 Memory Type         Total      Used       Free\r
 ----------------  --------   --------   --------\r
-Default                   8166         288       7878\r
-Near              27894        496       27398\r
-Far               8166         288       7878\r
+Default                   8166         806       7360\r
+Near              3414         712       2702\r
+Far               8166         806       7360\r
 ----------------  --------   --------   --------\r
-coreleft = 27396\r
-farcoreleft = 2352\r
-GetFreeSize = 40512\r
-GetNearFreeSize = 27398\r
-GetFarFreeSize = 40512\r
-memavl = 27396\r
-stackavail = 11792\r
+coreleft = 2700\r
+farcoreleft = 1694\r
+GetFreeSize = 64548\r
+GetNearFreeSize = 2702\r
+GetFarFreeSize = 64548\r
+memavl = 2700\r
+stackavail = 31519\r
index 2e06a768004248e1dfe1dac64e3bcd8b81c4e4bf..3d22065dd1aca2fa9facb54707c91e7df86925ca 100755 (executable)
Binary files a/MMDUMP.16B and b/MMDUMP.16B differ
index 0270a6dbc77f215efca654f6613044694ad7fb0a..89ef9446f1eb47b42c548c3efefa1f7440d0d34b 100755 (executable)
Binary files a/MMDUMP.16W and b/MMDUMP.16W differ
diff --git a/PROFILE.16W b/PROFILE.16W
new file mode 100755 (executable)
index 0000000..e69de29
index 9d1c2ae5dac26efd4b845a894173c649cc46b58c..e1d0305cc01f67f39d407bd22298c5dd3ba31b23 100755 (executable)
Binary files a/bcexmm.dsk and b/bcexmm.dsk differ
index d4ca4af8941a6d2e8f1b3552122810b957b51599..c11e9410f7921c01c97e813a8f41177b1fd6478e 100755 (executable)
Binary files a/bcexmm.exe and b/bcexmm.exe differ
index 6a7ef6315f8aa11cdcd50480cf8f75c87940f4a6..bf1d7a44a098ef77eef8b89799e6e3bd54a48a64 100755 (executable)
Binary files a/bcexmm.prj and b/bcexmm.prj differ
index 0ecbac33f44529d9701eae8c9b262c7da0f50416..f162c4cae406a47b40fe8f2dcf6140a03f8edf98 100755 (executable)
Binary files a/data/g.pal and b/data/g.pal differ
diff --git a/fmemtest.exe b/fmemtest.exe
new file mode 100755 (executable)
index 0000000..ee3480f
Binary files /dev/null and b/fmemtest.exe differ
diff --git a/fontgfx.exe b/fontgfx.exe
new file mode 100755 (executable)
index 0000000..d8891c5
Binary files /dev/null and b/fontgfx.exe differ
diff --git a/fonttest.exe b/fonttest.exe
new file mode 100755 (executable)
index 0000000..22505eb
Binary files /dev/null and b/fonttest.exe differ
diff --git a/inputest.exe b/inputest.exe
new file mode 100755 (executable)
index 0000000..0bc3916
Binary files /dev/null and b/inputest.exe differ
index 229299188fa596d3f1093cf0218c8f4713d60888..2d44a1b8e84fa7a08ae02b19e9e8d4e3b1cb04e1 100755 (executable)
--- a/makefile
+++ b/makefile
@@ -91,7 +91,7 @@ UPXQ=-qqq
 S_FLAGS=-sg -st -of+ -zu -zdf -zff -zgf -k32768#54096#60000
 Z_FLAGS=-zk0 -zc -zp8 -zm
 O_FLAGS=-obmilr -oe=24 -out -oh -ei -onac -ol+ -ok##x
-T_FLAGS=-bt=dos -mh -0 -fpi87 -fo=.$(OBJ) -d1
+T_FLAGS=-bt=dos -mh -0 -fpi87 -fo=.$(OBJ) -d1###### -e=65536
 
 CPPFLAGS=-DTARGET_MSDOS=16 -DMSDOS=1
 !ifeq DEBUGSERIAL 1
@@ -106,8 +106,8 @@ LIBFLAGS=$(WLIBQ) -b -n
 # objects
 #
 VGMSNDOBJ = vgmSnd.$(OBJ) 16_snd.$(OBJ)
-16LIBOBJS = 16_in.$(OBJ) 16_mm.$(OBJ) wcpu.$(OBJ) 16_head.$(OBJ) 16_ca.$(OBJ) 16_dbg.$(OBJ) kitten.$(OBJ) 16_hc.$(OBJ) 16_timer.$(OBJ)
-GFXLIBOBJS = modex16.$(OBJ) bitmap.$(OBJ) 16text.$(OBJ) bakapee.$(OBJ) scroll16.$(OBJ) 16render.$(OBJ) 16_vrs.$(OBJ) 16_sprit.$(OBJ) #scroll16.$(OBJ)
+GFXLIBOBJS = modex16.$(OBJ) bitmap.$(OBJ) 16text.$(OBJ) bakapee.$(OBJ) scroll16.$(OBJ) 16render.$(OBJ) 16_vrs.$(OBJ) 16_sprit.$(OBJ)
+16LIBOBJS = 16_mm.$(OBJ) 16_pm.$(OBJ) 16_ca.$(OBJ) 16_tail.$(OBJ) 16_in.$(OBJ) 16_head.$(OBJ) 16_dbg.$(OBJ) kitten.$(OBJ) 16_hc.$(OBJ) wcpu.$(OBJ) 16_timer.$(OBJ)
 #16planar.$(OBJ) planar.$(OBJ)
 DOSLIBOBJ = adlib.$(OBJ) 8254.$(OBJ) 8259.$(OBJ) dos.$(OBJ) cpu.$(OBJ)
 !ifeq DEBUGSERIAL 1
@@ -154,27 +154,30 @@ DOSLIBLIBS += $(DOSLIB_8250)/dos86h/8250.lib
 # List of executables to build
 #
 TESTEXEC = &
-    test.exe &
-    test0.exe &
-    pcxtest.exe &
-    pcxtest2.exe &
-    palettec.exe &
+    tesuto.exe &
+    0.exe &
+    scroll.exe &
+    zcroll.exe &
+    exmmtest.exe &
+    vrstest.exe
+TESTEXEC2 = &
+    vgmtest.exe &
+    inputest.exe &
     maptest.exe &
     fmemtest.exe &
     fonttest.exe &
     fontgfx.exe &
-    scroll.exe &
-    vgmtest.exe &
-    inputest.exe &
+    test.exe &
+    test0.exe &
+    pcxtest.exe &
+    pcxtest2.exe
+UTILEXEC = &
     palettel.exe &
-    exmmtest.exe &
-    vrstest.exe &
-    vgacamm.exe
+    palettec.exe
 EXEC = &
     16.exe &
     bakapi.exe &
-    tesuto.exe &
-    0.exe &
+    $(UTILEXEC) &
     $(TESTEXEC)
 
 all: $(EXEC) joytest.exe
@@ -190,6 +193,8 @@ bakapi.exe:       bakapi.$(OBJ) gfx.lib $(DOSLIBLIBS)
 #
 scroll.exe:       scroll.$(OBJ) mapread.$(OBJ) jsmn.$(OBJ) $(16LIB) gfx.lib $(DOSLIBLIBS)
 scroll.$(OBJ):    $(SRC)/scroll.c
+zcroll.exe:       zcroll.$(OBJ) mapread.$(OBJ) jsmn.$(OBJ) $(16LIB) gfx.lib $(DOSLIBLIBS)
+zcroll.$(OBJ):    $(SRC)/zcroll.c
 tesuto.exe:       tesuto.$(OBJ) 16_head.$(OBJ) gfx.lib $(DOSLIBLIBS)
 tesuto.$(OBJ):    $(SRC)/tesuto.c
 0.exe:            0.$(OBJ) $(16LIB) gfx.lib $(DOSLIBLIBS)
@@ -204,7 +209,7 @@ inputest.exe:     inputest.$(OBJ) $(16LIB) $(DOSLIBLIBS)
 #sountest.exe:    sountest.$(OBJ) $(16LIB)
 pcxtest.exe:      pcxtest.$(OBJ) gfx.lib $(DOSLIBLIBS)
 vrstest.exe:      vrstest.$(OBJ) $(16LIB) gfx.lib $(DOSLIBLIBS)
-vgacamm.exe:      vgacamm.$(OBJ) $(16LIB) gfx.lib $(DOSLIBLIBS)
+#vgacamm.exe:      vgacamm.$(OBJ) $(16LIB) gfx.lib $(DOSLIBLIBS)
 palettec.exe:     palettec.$(OBJ) gfx.lib $(DOSLIBLIBS)
 palettel.exe:     palettel.$(OBJ) gfx.lib $(DOSLIBLIBS)
 pcxtest2.exe:     pcxtest2.$(OBJ) gfx.lib $(DOSLIBLIBS)
@@ -224,7 +229,7 @@ test.$(OBJ):      $(SRC)/test.c $(SRCLIB)/modex16.h
 test0.$(OBJ):     $(SRC)/test0.c
 pcxtest.$(OBJ):   $(SRC)/pcxtest.c $(SRCLIB)/modex16.h
 vrstest.$(OBJ):   $(SRC)/vrstest.c $(SRCLIB)/modex16.h
-vgacamm.$(OBJ):   $(SRC)/vgacamm.c $(SRCLIB)/modex16.h
+#vgacamm.$(OBJ):   $(SRC)/vgacamm.c $(SRCLIB)/modex16.h
 #planrpcx.$(OBJ): $(SRC)/planrpcx.c $(SRCLIB)/modex16.h
 pcxtest2.$(OBJ):  $(SRC)/pcxtest2.c $(SRCLIB)/modex16.h
 palettec.$(OBJ):  $(SRC)/palettec.c
@@ -288,10 +293,12 @@ mapread.$(OBJ):   $(SRCLIB)/mapread.c $(SRCLIB)/mapread.h
 16_timer.$(OBJ):  $(SRCLIB)/16_timer.c $(SRCLIB)/16_timer.h
 16_in.$(OBJ):     $(SRCLIB)/16_in.c $(SRCLIB)/16_in.h
 16_mm.$(OBJ):     $(SRCLIB)/16_mm.c $(SRCLIB)/16_mm.h
+16_pm.$(OBJ):     $(SRCLIB)/16_pm.c $(SRCLIB)/16_pm.h
 16_ca.$(OBJ):     $(SRCLIB)/16_ca.c $(SRCLIB)/16_ca.h
 16_dbg.$(OBJ):    $(SRCLIB)/16_dbg.c $(SRCLIB)/16_dbg.h
 midi.$(OBJ):      $(SRCLIB)/midi.c $(SRCLIB)/midi.h
 16_head.$(OBJ):   $(SRCLIB)/16_head.c $(SRCLIB)/16_head.h
+16_tail.$(OBJ):   $(SRCLIB)/16_tail.c $(SRCLIB)/16_tail.h
 16_hc.$(OBJ):     $(SRCLIB)/16_hc.c $(SRCLIB)/16_hc.h
 16_snd.$(OBJ):    $(SRCLIB)/16_snd.c $(SRCLIB)/16_snd.h
 jsmn.$(OBJ):      $(JSMNLIB)/jsmn.c $(JSMNLIB)/jsmn.h
diff --git a/maptest.exe b/maptest.exe
new file mode 100755 (executable)
index 0000000..e8e04a6
Binary files /dev/null and b/maptest.exe differ
diff --git a/modex.lib b/modex.lib
deleted file mode 100755 (executable)
index 560a1c6..0000000
Binary files a/modex.lib and /dev/null differ
diff --git a/pcxtest.exe b/pcxtest.exe
new file mode 100755 (executable)
index 0000000..9f5b821
Binary files /dev/null and b/pcxtest.exe differ
diff --git a/pcxtest2.exe b/pcxtest2.exe
new file mode 100755 (executable)
index 0000000..ef3287a
Binary files /dev/null and b/pcxtest2.exe differ
diff --git a/pm.use b/pm.use
new file mode 100755 (executable)
index 0000000..fbd7a2c
--- /dev/null
+++ b/pm.use
@@ -0,0 +1,277 @@
+16/wf3d8086/contigsc.c:        shape = PM_GetSpritePage (shapenum);\r
+16/wf3d8086/contigsc.c:        shape = PM_GetSpritePage (shapenum);\r
+16/wf3d8086/id_pm.c:// PM_SetMainMemPurge() - Sets the purge level for all allocated main memory\r
+16/wf3d8086/id_pm.c://         blocks. This shouldn't be called directly - the PM_LockMainMem() and\r
+16/wf3d8086/id_pm.c://         PM_UnlockMainMem() macros should be used instead.\r
+16/wf3d8086/id_pm.c:PM_SetMainMemPurge(int level)\r
+16/wf3d8086/id_pm.c:// PM_CheckMainMem() - If something besides the Page Mgr makes requests of\r
+16/wf3d8086/id_pm.c:// This routine now calls PM_LockMainMem() to make sure that any allocation\r
+16/wf3d8086/id_pm.c://         of the other blocks. Because PM_LockMainMem() is called,\r
+16/wf3d8086/id_pm.c://         PM_UnlockMainMem() needs to be called before any other part of the\r
+16/wf3d8086/id_pm.c:PM_CheckMainMem(void)\r
+16/wf3d8086/id_pm.c:   PM_LockMainMem();\r
+16/wf3d8086/id_pm.c://         necessary to make requests of the Memory Mgr, PM_UnlockMainMem()\r
+16/wf3d8086/id_pm.c:           Quit("PM_SetupMainMem: Not enough main memory");\r
+16/wf3d8086/id_pm.c:// PM_GetPageAddress() - Returns the address of a given page\r
+16/wf3d8086/id_pm.c:PM_GetPageAddress(int pagenum)\r
+16/wf3d8086/id_pm.c:   PML_CopyToXMS(PM_GetPageAddress(pagenum),page->xmsPage,page->length);\r
+16/wf3d8086/id_pm.c:   addr = PM_GetPageAddress(orig);\r
+16/wf3d8086/id_pm.c:// PM_GetPage() - Returns the address of the page, loading it if necessary\r
+16/wf3d8086/id_pm.c:PM_GetPage(int pagenum)\r
+16/wf3d8086/id_pm.c:           Quit("PM_GetPage: Invalid page request");\r
+16/wf3d8086/id_pm.c:   if (!(result = PM_GetPageAddress(pagenum)))\r
+16/wf3d8086/id_pm.c:                   result = PM_GetPageAddress(pagenum);\r
+16/wf3d8086/id_pm.c:// PM_SetPageLock() - Sets the lock type on a given page\r
+16/wf3d8086/id_pm.c:PM_SetPageLock(int pagenum,PMLockType lock)\r
+16/wf3d8086/id_pm.c:           Quit("PM_SetPageLock: Locking/unlocking non-sound page");\r
+16/wf3d8086/id_pm.c:// PM_Preload() - Loads as many pages as possible into all types of memory.\r
+16/wf3d8086/id_pm.c:PM_Preload(boolean (*update)(word current,word total))\r
+16/wf3d8086/id_pm.c:                   Quit ("PM_Preload: Pages>=ChunksInFile");\r
+16/wf3d8086/id_pm.c:           PM_GetPage(page);\r
+16/wf3d8086/id_pm.c:           addr = PM_GetPage(oogypage);\r
+16/wf3d8086/id_pm.c:                   Quit("PM_Preload: XMS buffer failed");\r
+16/wf3d8086/id_pm.c:                           Quit ("PM_Preload: Pages>=ChunksInFile");\r
+16/wf3d8086/id_pm.c:                           Quit("PM_Preload: Exceeded XMS pages");\r
+16/wf3d8086/id_pm.c:                           Quit("PM_Preload: Page too long");\r
+16/wf3d8086/id_pm.c:// PM_NextFrame() - Increments the frame counter and adjusts the thrash\r
+16/wf3d8086/id_pm.c:PM_NextFrame(void)\r
+16/wf3d8086/id_pm.c:                   sprintf(buf,"PM_NextFrame: Page %d is locked",i);\r
+16/wf3d8086/id_pm.c:// PM_Reset() - Sets up caching structures\r
+16/wf3d8086/id_pm.c:PM_Reset(void)\r
+16/wf3d8086/id_pm.c:// PM_Startup() - Start up the Page Mgr\r
+16/wf3d8086/id_pm.c:PM_Startup(void)\r
+16/wf3d8086/id_pm.c:           Quit("PM_Startup: No main or EMS");\r
+16/wf3d8086/id_pm.c:   PM_Reset();\r
+16/wf3d8086/id_pm.c:// PM_Shutdown() - Shut down the Page Mgr\r
+16/wf3d8086/id_pm.c:PM_Shutdown(void)\r
+16/wf3d8086/id_pm.h:#define    PM_GetSoundPage(v)      PM_GetPage(PMSoundStart + (v))\r
+16/wf3d8086/id_pm.h:#define    PM_GetSpritePage(v)     PM_GetPage(PMSpriteStart + (v))\r
+16/wf3d8086/id_pm.h:#define    PM_LockMainMem()        PM_SetMainMemPurge(0)\r
+16/wf3d8086/id_pm.h:#define    PM_UnlockMainMem()      PM_SetMainMemPurge(3)\r
+16/wf3d8086/id_pm.h:extern     void    PM_Startup(void),\r
+16/wf3d8086/id_pm.h:                           PM_Shutdown(void),\r
+16/wf3d8086/id_pm.h:                           PM_Reset(void),\r
+16/wf3d8086/id_pm.h:                           PM_Preload(boolean (*update)(word current,word total)),\r
+16/wf3d8086/id_pm.h:                           PM_NextFrame(void),\r
+16/wf3d8086/id_pm.h:                           PM_SetPageLock(int pagenum,PMLockType lock),\r
+16/wf3d8086/id_pm.h:                           PM_SetMainPurge(int level),\r
+16/wf3d8086/id_pm.h:                           PM_CheckMainMem(void);\r
+16/wf3d8086/id_pm.h:extern     memptr  PM_GetPageAddress(int pagenum),\r
+16/wf3d8086/id_pm.h:                           PM_GetPage(int pagenum);                // Use this one to cache page\r
+16/wf3d8086/id_pm.h:void PM_SetMainMemPurge(int level);\r
+16/wf3d8086/id_sd.c:   addr = PM_GetSoundPage(page);\r
+16/wf3d8086/id_sd.c:   PM_SetPageLock(PMSoundStart + page,pml_Locked);\r
+16/wf3d8086/id_sd.c:           PM_SetPageLock(i + PMSoundStart,pml_Unlocked);\r
+16/wf3d8086/id_sd.c:   PM_UnlockMainMem();\r
+16/wf3d8086/id_sd.c:   PM_CheckMainMem();\r
+16/wf3d8086/id_sd.c:   p = (word far *)MK_FP(PM_GetPage(ChunksInFile - 1),0);\r
+16/wf3d8086/id_sd.c:   PM_UnlockMainMem();\r
+Binary file 16/wf3d8086/obj/wolf3d.exe matches\r
+16/wf3d8086/obj/wolf3d.map: 1A268H 1B44AH 011E3H ID_PM_TEXT         CODE\r
+16/wf3d8086/obj/wolf3d.map: 1A26:0008 11E3 C=CODE   S=ID_PM_TEXT     G=(none)  M=ID_PM.C    ACBP=28\r
+16/wf3d8086/obj/wolf3d.map: 1A26:02F3       _PM_CheckMainMem\r
+16/wf3d8086/obj/wolf3d.map: 1A26:0CDE       _PM_GetPage\r
+16/wf3d8086/obj/wolf3d.map: 1A26:080D       _PM_GetPageAddress\r
+16/wf3d8086/obj/wolf3d.map: 1A26:1036       _PM_NextFrame\r
+16/wf3d8086/obj/wolf3d.map: 1A26:0DD0       _PM_Preload\r
+16/wf3d8086/obj/wolf3d.map: 1A26:10B0 idle  _PM_Reset\r
+16/wf3d8086/obj/wolf3d.map: 1A26:02CA       _PM_SetMainMemPurge\r
+16/wf3d8086/obj/wolf3d.map: 1A26:0DA0       _PM_SetPageLock\r
+16/wf3d8086/obj/wolf3d.map: 1A26:11CF       _PM_Shutdown\r
+16/wf3d8086/obj/wolf3d.map: 1A26:111E       _PM_Startup\r
+16/wf3d8086/obj/wolf3d.map: 1A26:02CA       _PM_SetMainMemPurge\r
+16/wf3d8086/obj/wolf3d.map: 1A26:02F3       _PM_CheckMainMem\r
+16/wf3d8086/obj/wolf3d.map: 1A26:080D       _PM_GetPageAddress\r
+16/wf3d8086/obj/wolf3d.map: 1A26:0CDE       _PM_GetPage\r
+16/wf3d8086/obj/wolf3d.map: 1A26:0DA0       _PM_SetPageLock\r
+16/wf3d8086/obj/wolf3d.map: 1A26:0DD0       _PM_Preload\r
+16/wf3d8086/obj/wolf3d.map: 1A26:1036       _PM_NextFrame\r
+16/wf3d8086/obj/wolf3d.map: 1A26:10B0 idle  _PM_Reset\r
+16/wf3d8086/obj/wolf3d.map: 1A26:111E       _PM_Startup\r
+16/wf3d8086/obj/wolf3d.map: 1A26:11CF       _PM_Shutdown\r
+16/wf3d8086/oldscale.c:        shape = PM_GetSpritePage (shapenum);\r
+16/wf3d8086/oldscale.c:        shape = PM_GetSpritePage (shapenum);\r
+16/wf3d8086/wl_act2.c: PM_UnlockMainMem ();\r
+16/wf3d8086/wl_act2.c: PM_CheckMainMem ();\r
+16/wf3d8086/wl_debug.c:                addr = PM_GetPageAddress(i);\r
+16/wf3d8086/wl_debug.c:                                PM_GetPage(j);\r
+16/wf3d8086/wl_debug.c:                        PM_GetPage(i);\r
+16/wf3d8086/wl_draw.c:         *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+16/wf3d8086/wl_draw.c:         *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+16/wf3d8086/wl_draw.c:         *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage);\r
+16/wf3d8086/wl_draw.c:         *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage+1);\r
+16/wf3d8086/wl_draw.c:         *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+16/wf3d8086/wl_draw.c:         *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+16/wf3d8086/wl_draw.c: PM_NextFrame();\r
+16/wf3d8086/wl_game.c: PM_UnlockMainMem();\r
+16/wf3d8086/wl_game.c: PM_CheckMainMem ();\r
+16/wf3d8086/wl_game.c: PM_CheckMainMem ();\r
+16/wf3d8086/wl_game.c:         PM_CheckMainMem ();\r
+16/wf3d8086/wl_game.c:                 PM_CheckMainMem ();\r
+16/wf3d8086/wl_inter.c:        PM_Preload (PreloadUpdate);\r
+16/wf3d8086/wl_main.c: PM_Shutdown ();\r
+16/wf3d8086/wl_main.c: PM_Startup ();\r
+16/wf3d8086/wl_main.c: PM_UnlockMainMem ();\r
+16/wf3d8086/wl_menu.c:                         PM_CheckMainMem ();\r
+16/wf3d8086/wl_menu.c:                         PM_CheckMainMem ();\r
+16/wf3d8086/wl_play.c:         PM_CheckMainMem ();\r
+16/wf3d8086/wl_play.c:  PM_CheckMainMem ();\r
+16/wf3d8086/wl_play.c:  PM_CheckMainMem ();\r
+16/wf3d8086/wl_play.c:         PM_CheckMainMem ();\r
+16/wf3d8086/wl_play.c:         PM_CheckMainMem ();\r
+16/wf3d8086/wl_scale.c:        shape = PM_GetSpritePage (shapenum);\r
+16/wf3d8086/wl_scale.c:        shape = PM_GetSpritePage (shapenum);\r
+16/wf3d8086/wolf3d.map: 19127H 1A286H 01160H ID_PM_TEXT         CODE\r
+16/wf3d8086/wolf3d.map: 1912:0007 1160 C=CODE   S=ID_PM_TEXT     G=(none)  M=ID_PM.C    ACBP=28\r
+16/wf3d8086/wolf3d.map: 1912:02DF       _PM_CheckMainMem\r
+16/wf3d8086/wolf3d.map: 1912:0C71       _PM_GetPage\r
+16/wf3d8086/wolf3d.map: 1912:07BF       _PM_GetPageAddress\r
+16/wf3d8086/wolf3d.map: 1912:0FBA       _PM_NextFrame\r
+16/wf3d8086/wolf3d.map: 1912:0D60       _PM_Preload\r
+16/wf3d8086/wolf3d.map: 1912:1034 idle  _PM_Reset\r
+16/wf3d8086/wolf3d.map: 1912:02B8       _PM_SetMainMemPurge\r
+16/wf3d8086/wolf3d.map: 1912:0D31       _PM_SetPageLock\r
+16/wf3d8086/wolf3d.map: 1912:114B       _PM_Shutdown\r
+16/wf3d8086/wolf3d.map: 1912:10A0       _PM_Startup\r
+16/wf3d8086/wolf3d.map: 1912:02B8       _PM_SetMainMemPurge\r
+16/wf3d8086/wolf3d.map: 1912:02DF       _PM_CheckMainMem\r
+16/wf3d8086/wolf3d.map: 1912:07BF       _PM_GetPageAddress\r
+16/wf3d8086/wolf3d.map: 1912:0C71       _PM_GetPage\r
+16/wf3d8086/wolf3d.map: 1912:0D31       _PM_SetPageLock\r
+16/wf3d8086/wolf3d.map: 1912:0D60       _PM_Preload\r
+16/wf3d8086/wolf3d.map: 1912:0FBA       _PM_NextFrame\r
+16/wf3d8086/wolf3d.map: 1912:1034 idle  _PM_Reset\r
+16/wf3d8086/wolf3d.map: 1912:10A0       _PM_Startup\r
+16/wf3d8086/wolf3d.map: 1912:114B       _PM_Shutdown\r
+16/wf3d8086/wolfhack.c:        src = PM_GetPage(0);\r
+16/wf3d8086/wolfhack.c:        src = PM_GetPage(1);\r
+16/wolf3d/WOLFSRC/CONTIGSC.C:  shape = PM_GetSpritePage (shapenum);\r
+16/wolf3d/WOLFSRC/CONTIGSC.C:  shape = PM_GetSpritePage (shapenum);\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_SetMainMemPurge() - Sets the purge level for all allocated main memory\r
+16/wolf3d/WOLFSRC/ID_PM.C://           blocks. This shouldn't be called directly - the PM_LockMainMem() and\r
+16/wolf3d/WOLFSRC/ID_PM.C://           PM_UnlockMainMem() macros should be used instead.\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_SetMainMemPurge(int level)\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_CheckMainMem() - If something besides the Page Mgr makes requests of\r
+16/wolf3d/WOLFSRC/ID_PM.C://   This routine now calls PM_LockMainMem() to make sure that any allocation\r
+16/wolf3d/WOLFSRC/ID_PM.C://           of the other blocks. Because PM_LockMainMem() is called,\r
+16/wolf3d/WOLFSRC/ID_PM.C://           PM_UnlockMainMem() needs to be called before any other part of the\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_CheckMainMem(void)\r
+16/wolf3d/WOLFSRC/ID_PM.C:     PM_LockMainMem();\r
+16/wolf3d/WOLFSRC/ID_PM.C://           necessary to make requests of the Memory Mgr, PM_UnlockMainMem()\r
+16/wolf3d/WOLFSRC/ID_PM.C:             Quit("PM_SetupMainMem: Not enough main memory");\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_GetPageAddress() - Returns the address of a given page\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_GetPageAddress(int pagenum)\r
+16/wolf3d/WOLFSRC/ID_PM.C:     PML_CopyToXMS(PM_GetPageAddress(pagenum),page->xmsPage,page->length);\r
+16/wolf3d/WOLFSRC/ID_PM.C:     addr = PM_GetPageAddress(orig);\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_GetPage() - Returns the address of the page, loading it if necessary\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_GetPage(int pagenum)\r
+16/wolf3d/WOLFSRC/ID_PM.C:             Quit("PM_GetPage: Invalid page request");\r
+16/wolf3d/WOLFSRC/ID_PM.C:     if (!(result = PM_GetPageAddress(pagenum)))\r
+16/wolf3d/WOLFSRC/ID_PM.C:                     result = PM_GetPageAddress(pagenum);\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_SetPageLock() - Sets the lock type on a given page\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_SetPageLock(int pagenum,PMLockType lock)\r
+16/wolf3d/WOLFSRC/ID_PM.C:             Quit("PM_SetPageLock: Locking/unlocking non-sound page");\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_Preload() - Loads as many pages as possible into all types of memory.\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_Preload(boolean (*update)(word current,word total))\r
+16/wolf3d/WOLFSRC/ID_PM.C:                     Quit ("PM_Preload: Pages>=ChunksInFile");\r
+16/wolf3d/WOLFSRC/ID_PM.C:             PM_GetPage(page);\r
+16/wolf3d/WOLFSRC/ID_PM.C:             addr = PM_GetPage(oogypage);\r
+16/wolf3d/WOLFSRC/ID_PM.C:                     Quit("PM_Preload: XMS buffer failed");\r
+16/wolf3d/WOLFSRC/ID_PM.C:                             Quit ("PM_Preload: Pages>=ChunksInFile");\r
+16/wolf3d/WOLFSRC/ID_PM.C:                             Quit("PM_Preload: Exceeded XMS pages");\r
+16/wolf3d/WOLFSRC/ID_PM.C:                             Quit("PM_Preload: Page too long");\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_NextFrame() - Increments the frame counter and adjusts the thrash\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_NextFrame(void)\r
+16/wolf3d/WOLFSRC/ID_PM.C:                     sprintf(buf,"PM_NextFrame: Page %d is locked",i);\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_Reset() - Sets up caching structures\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_Reset(void)\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_Startup() - Start up the Page Mgr\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_Startup(void)\r
+16/wolf3d/WOLFSRC/ID_PM.C:             Quit("PM_Startup: No main or EMS");\r
+16/wolf3d/WOLFSRC/ID_PM.C:     PM_Reset();\r
+16/wolf3d/WOLFSRC/ID_PM.C://   PM_Shutdown() - Shut down the Page Mgr\r
+16/wolf3d/WOLFSRC/ID_PM.C:PM_Shutdown(void)\r
+16/wolf3d/WOLFSRC/ID_PM.H:#define      PM_GetSoundPage(v)      PM_GetPage(PMSoundStart + (v))\r
+16/wolf3d/WOLFSRC/ID_PM.H:#define      PM_GetSpritePage(v)     PM_GetPage(PMSpriteStart + (v))\r
+16/wolf3d/WOLFSRC/ID_PM.H:#define      PM_LockMainMem()        PM_SetMainMemPurge(0)\r
+16/wolf3d/WOLFSRC/ID_PM.H:#define      PM_UnlockMainMem()      PM_SetMainMemPurge(3)\r
+16/wolf3d/WOLFSRC/ID_PM.H:extern       void    PM_Startup(void),\r
+16/wolf3d/WOLFSRC/ID_PM.H:                             PM_Shutdown(void),\r
+16/wolf3d/WOLFSRC/ID_PM.H:                             PM_Reset(void),\r
+16/wolf3d/WOLFSRC/ID_PM.H:                             PM_Preload(boolean (*update)(word current,word total)),\r
+16/wolf3d/WOLFSRC/ID_PM.H:                             PM_NextFrame(void),\r
+16/wolf3d/WOLFSRC/ID_PM.H:                             PM_SetPageLock(int pagenum,PMLockType lock),\r
+16/wolf3d/WOLFSRC/ID_PM.H:                             PM_SetMainPurge(int level),\r
+16/wolf3d/WOLFSRC/ID_PM.H:                             PM_CheckMainMem(void);\r
+16/wolf3d/WOLFSRC/ID_PM.H:extern       memptr  PM_GetPageAddress(int pagenum),\r
+16/wolf3d/WOLFSRC/ID_PM.H:                             PM_GetPage(int pagenum);                // Use this one to cache page\r
+16/wolf3d/WOLFSRC/ID_PM.H:void PM_SetMainMemPurge(int level);\r
+16/wolf3d/WOLFSRC/ID_SD.C:     addr = PM_GetSoundPage(page);\r
+16/wolf3d/WOLFSRC/ID_SD.C:     PM_SetPageLock(PMSoundStart + page,pml_Locked);\r
+16/wolf3d/WOLFSRC/ID_SD.C:             PM_SetPageLock(i + PMSoundStart,pml_Unlocked);\r
+16/wolf3d/WOLFSRC/ID_SD.C:     PM_UnlockMainMem();\r
+16/wolf3d/WOLFSRC/ID_SD.C:     PM_CheckMainMem();\r
+16/wolf3d/WOLFSRC/ID_SD.C:     p = (word far *)MK_FP(PM_GetPage(ChunksInFile - 1),0);\r
+16/wolf3d/WOLFSRC/ID_SD.C:     PM_UnlockMainMem();\r
+16/wolf3d/WOLFSRC/OLDSCALE.C:  shape = PM_GetSpritePage (shapenum);\r
+16/wolf3d/WOLFSRC/OLDSCALE.C:  shape = PM_GetSpritePage (shapenum);\r
+16/wolf3d/WOLFSRC/WL_ACT2.C:   PM_UnlockMainMem ();\r
+16/wolf3d/WOLFSRC/WL_ACT2.C:   PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_DEBUG.C:          addr = PM_GetPageAddress(i);\r
+16/wolf3d/WOLFSRC/WL_DEBUG.C:                          PM_GetPage(j);\r
+16/wolf3d/WOLFSRC/WL_DEBUG.C:                  PM_GetPage(i);\r
+16/wolf3d/WOLFSRC/WL_DRAW.C:           *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+16/wolf3d/WOLFSRC/WL_DRAW.C:           *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+16/wolf3d/WOLFSRC/WL_DRAW.C:           *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage);\r
+16/wolf3d/WOLFSRC/WL_DRAW.C:           *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage+1);\r
+16/wolf3d/WOLFSRC/WL_DRAW.C:           *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+16/wolf3d/WOLFSRC/WL_DRAW.C:           *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+16/wolf3d/WOLFSRC/WL_DRAW.C:   PM_NextFrame();\r
+16/wolf3d/WOLFSRC/WL_GAME.C:   PM_UnlockMainMem();\r
+16/wolf3d/WOLFSRC/WL_GAME.C:   PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_GAME.C:   PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_GAME.C:           PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_GAME.C:                   PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_INTER.C:  PM_Preload (PreloadUpdate);\r
+16/wolf3d/WOLFSRC/WL_MAIN.C:   PM_Shutdown ();\r
+16/wolf3d/WOLFSRC/WL_MAIN.C:   PM_Startup ();\r
+16/wolf3d/WOLFSRC/WL_MAIN.C:   PM_UnlockMainMem ();\r
+16/wolf3d/WOLFSRC/WL_MENU.C:                           PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_MENU.C:                           PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_PLAY.C:           PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_PLAY.C:    PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_PLAY.C:    PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_PLAY.C:           PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_PLAY.C:           PM_CheckMainMem ();\r
+16/wolf3d/WOLFSRC/WL_SCALE.C:  shape = PM_GetSpritePage (shapenum);\r
+16/wolf3d/WOLFSRC/WL_SCALE.C:  shape = PM_GetSpritePage (shapenum);\r
+Binary file 16/wolf3d/WOLFSRC/WOLF3D.EXE matches\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 19127H 1A286H 01160H ID_PM_TEXT         CODE\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:0007 1160 C=CODE   S=ID_PM_TEXT     G=(none)  M=ID_PM.C    ACBP=28\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:02DF       _PM_CheckMainMem\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:0C71       _PM_GetPage\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:07BF       _PM_GetPageAddress\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:0FBA       _PM_NextFrame\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:0D60       _PM_Preload\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:1034 idle  _PM_Reset\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:02B8       _PM_SetMainMemPurge\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:0D31       _PM_SetPageLock\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:114B       _PM_Shutdown\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:10A0       _PM_Startup\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:02B8       _PM_SetMainMemPurge\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:02DF       _PM_CheckMainMem\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:07BF       _PM_GetPageAddress\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:0C71       _PM_GetPage\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:0D31       _PM_SetPageLock\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:0D60       _PM_Preload\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:0FBA       _PM_NextFrame\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:1034 idle  _PM_Reset\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:10A0       _PM_Startup\r
+16/wolf3d/WOLFSRC/WOLF3D.MAP: 1912:114B       _PM_Shutdown\r
+16/wolf3d/WOLFSRC/WOLFHACK.C:  src = PM_GetPage(0);\r
+16/wolf3d/WOLFSRC/WOLFHACK.C:  src = PM_GetPage(1);\r
+\r
+16/wf3d8086/id_pm.c:           longword last = MAXLONG;\r
+16/wf3d8086/id_pm.c:   for (i = 0,page = PMPages,lru = -1,last = MAXLONG;i < ChunksInFile;i++,page++)\r
+16/wf3d8086/id_pm.c:   for (i = 0,page = PMPages,lru = -1,last = MAXLONG;i < ChunksInFile;i++,page++)\r
+16/wf3d8086/id_pm.c:   if (++PMFrameCount >= MAXLONG - 4)\r
diff --git a/src/0.c b/src/0.c
index ae51d0582567000e69f387bae1740df8d9378c8c..09e8953df6d271e368b80d0486d15f9d755393e3 100755 (executable)
--- a/src/0.c
+++ b/src/0.c
-#include <hw/cpu/cpu.h>
-#include <hw/dos/dos.h>
-#include <hw/vga/vga.h>
-#include <hw/vga/vrl.h>
-
-#include "src/tesuto.h"
-
-#define FILENAME_1 "data/aconita.vrl"
-#define FILENAME_2 "data/aconita.pal"
-
-static unsigned char palette[768];
-global_game_variables_t gvar;
-player_t player[1];
-
-int main(int argc,char **argv) {
-       struct vrl1_vgax_header *vrl_header;
-       vrl1_vgax_offset_t *vrl_lineoffs;
-       unsigned char *buffer;
-       unsigned int bufsz;
-       int fd;
-       char *bakapee1,*bakapee2;
-
-       bakapee1=malloc(64);
-       bakapee2=malloc(1024);
-
-       IN_Startup();
-       IN_Default(0,&player,ctrl_Joystick);
-       IN_initplayer(&player, 0);
-
-       if (argc < 3) {
-               fprintf(stderr,"drawvrl <VRL file> <palette file>\n");
-               bakapee1 = FILENAME_1;//"data/aconita.vrl";
-               bakapee2 = FILENAME_2;//"data/aconita.pal";
-               //return 1;
-       }else{
-               if(argv[1]) bakapee1 = argv[1];
-               if(argv[2]) bakapee2 = argv[2];
-       }
-
-       fd = open(bakapee1,O_RDONLY|O_BINARY);
-       if (fd < 0) {
-               fprintf(stderr,"Unable to open '%s'\n", bakapee1);
-               return 1;
-       }
-       {
-               unsigned long sz = lseek(fd,0,SEEK_END);
-               if (sz < sizeof(*vrl_header)) return 1;
-               if (sz >= 65535UL) return 1;
-
-               bufsz = (unsigned int)sz;
-               buffer = malloc(bufsz);
-               if (buffer == NULL) return 1;
-
-               lseek(fd,0,SEEK_SET);
-               if ((unsigned int)read(fd,buffer,bufsz) < bufsz) return 1;
-
-               vrl_header = (struct vrl1_vgax_header*)buffer;
-               if (memcmp(vrl_header->vrl_sig,"VRL1",4) || memcmp(vrl_header->fmt_sig,"VGAX",4)) return 1;
-               if (vrl_header->width == 0 || vrl_header->height == 0) return 1;
-       }
-       close(fd);
-
-       probe_dos();
-       if (!probe_vga()) {
-               printf("VGA probe failed\n");
-               return 1;
-       }
-       VGAmodeX(1, 1, &gvar);
-
-       /* load color palette */
-       fd = open(bakapee2,O_RDONLY|O_BINARY);
-       if (fd >= 0) {
-               unsigned int i;
-
-               read(fd,palette,768);
-               close(fd);
-
-               vga_palette_lseek(0);
-               for (i=0;i < 256;i++) vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);
-       }
-
-       /* preprocess the sprite to generate line offsets */
-       vrl_lineoffs = vrl1_vgax_genlineoffsets(vrl_header,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));
-       if (vrl_lineoffs == NULL) return 1;
-
-       /* setup camera and screen~ */
-       modexHiganbanaPageSetup(&gvar.video);
-       gvar.video.page[1].dx=gvar.video.page[0].dx=16;
-       gvar.video.page[1].dy=gvar.video.page[0].dy=16;
-       modexShowPage(&(gvar.video.page[0]));
-
-       #define VMEMHEIGHT gvar.video.page[0].height+gvar.video.page[1].height
-
-       //4     this dose the screen
-       {
-               unsigned int i,j,o;
-               /* fill screen with a distinctive pattern */
-               for (i=0;i < gvar.video.page[0].width;i++) {
-                       o = i >> 2;
-                       vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
-                       for (j=0;j < VMEMHEIGHT;j++,o += gvar.video.page[0].stridew)
-                               vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
-               }
-       }
-
-       //while (getch() != 13);
-
-       /* make distinctive pattern offscreen, render sprite, copy onscreen.
-        * this time, we render the distinctive pattern to another offscreen location and just copy.
-        * note this version is much faster too! */
-       {
-               unsigned int i,j,o,o2;
-               int x,y,rx,ry,w,h;
-               unsigned int overdraw = 1;      // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks.
-                                               // if the sprite's edge pixels are clear anyway, you can set this to 0.
-               VGA_RAM_PTR omemptr;
-               int xdir=1,ydir=1;
-
-               //4     this dose the sprite? wwww
-               /* fill pattern offset with a distinctive pattern */
-               for (i=0;i < gvar.video.page[0].width;i++) {
-                       o = (i >> 2) + (0x10000UL - (uint16_t)gvar.video.page[1].data);
-                       vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
-                       for (j=0;j < VMEMHEIGHT;j++,o += gvar.video.page[0].stridew)
-                               vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
-               }
-
-               /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */
-               x = 0;
-               y = 0;
-
-               /* do it */
-               omemptr = vga_state.vga_graphics_ram; // save original mem ptr
-
-               while(!IN_KeyDown(sc_Escape))
-               {
-                       IN_ReadControl(0,&player);
-                       if(IN_KeyDown(2)) modexShowPage(&(gvar.video.page[0]));
-                       if(IN_KeyDown(3)) modexShowPage(&(gvar.video.page[1]));
-                       if(IN_KeyDown(68))      //f10
-                       {
-                               //gvar.kurokku.fpscap=!gvar.kurokku.fpscap;
-                               IN_UserInput(1,1);
-                       }
-
-                       /* render box bounds. y does not need modification, but x and width must be multiple of 4 */
-                       if (x >= overdraw) rx = (x - overdraw) & (~3);
-                       else rx = -(gvar.video.page[0].dx);
-                       if (y >= overdraw) ry = (y - overdraw);
-                       else ry = -(gvar.video.page[0].dy);
-                       h = vrl_header->height + overdraw + y - ry;
-                       w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3);
-                       if ((rx+w) > gvar.video.page[0].width) w = gvar.video.page[0].width-rx;
-                       if ((ry+h) > gvar.video.page[0].height) h = (gvar.video.page[0].height)-ry;
-
-                       /* block copy pattern to where we will draw the sprite */
-                       vga_setup_wm1_block_copy();
-                       o2 = gvar.video.page[0].pagesize;
-                       o = (0x10000UL - (uint16_t)gvar.video.page[1].data) + (ry * gvar.video.page[0].stridew) + (rx >> 2); // source offscreen
-                       for (i=0;i < h;i++,o += gvar.video.page[0].stridew,o2 += (w >> 2)) vga_wm1_mem_block_copy(o2,o,w >> 2);
-                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */
-                       vga_restore_rm0wm0();
-
-                       /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */
-                       vga_state.vga_draw_stride_limit = (gvar.video.page[0].width + 3/*round up*/ - x) >> 2;
-                       vga_state.vga_draw_stride = w >> 2;
-                       vga_state.vga_graphics_ram = omemptr + gvar.video.page[0].pagesize;
-
-                       /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */
-                       draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));
-
-                       /* restore ptr */
-                       vga_state.vga_graphics_ram = omemptr;
-
-                       /* block copy to visible RAM from offscreen */
-                       vga_setup_wm1_block_copy();
-                       o = gvar.video.page[0].pagesize; // source offscreen
-                       o2 = (ry * gvar.video.page[0].stridew) + (rx >> 2); // dest visible (original stride)
-                       for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += gvar.video.page[0].stridew) vga_wm1_mem_block_copy(o2,o,w >> 2);
-                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */
-                       vga_restore_rm0wm0();
-
-                       /* restore stride */
-                       vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = gvar.video.page[0].stridew;
-
-                       /* step */
-                       x += xdir; y += ydir;
-                       if ((x + vrl_header->width) >= ((gvar.video.page[0].width + gvar.video.page[0].dx) - 1) || x == -(gvar.video.page[0].dx))
-                               xdir = -xdir;
-                       if ((y + vrl_header->height) >= ((gvar.video.page[0].height + gvar.video.page[0].dy) - 1) || y == -(gvar.video.page[0].dy))
-                               ydir = -ydir;
-                       //printf("[x%u y%u]     [rx%u ry%u]             [w%u h%u]\n", x, y, rx, ry, w, h);
-               }
-       }
-
-       IN_UserInput(1,1);
-
-       while(!IN_KeyDown(sc_Escape))
-       {
-               if(IN_KeyDown(2)) modexShowPage(&(gvar.video.page[0]));
-               if(IN_KeyDown(3)) modexShowPage(&(gvar.video.page[1]));
-       }
-
-       modexShowPage(&(gvar.video.page[0]));
-       /* another handy "demo" effect using VGA write mode 1.
-        * we can take what's on screen and vertically squash it like an old analog TV set turning off. */
-       {
-               unsigned int blank_line_ofs = (gvar.video.page[0].stridew * gvar.video.page[0].height * 2);
-               unsigned int copy_ofs = (gvar.video.page[0].stridew * gvar.video.page[0].height);
-               unsigned int display_ofs = 0x0000;
-               unsigned int i,y,soh,doh,dstart;
-               unsigned int dh_blankfill = 8;
-               unsigned int dh_step = 8;
-               uint32_t sh,dh,yf,ystep;
-
-               /* copy active display (0) to offscreen buffer (0x4000) */
-               vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = gvar.video.page[0].stridew;
-               vga_setup_wm1_block_copy();
-               vga_wm1_mem_block_copy(copy_ofs,display_ofs,gvar.video.page[0].stridew * gvar.video.page[0].height);
-               vga_restore_rm0wm0();
-
-               /* need a blank line as well */
-               for (i=0;i < gvar.video.page[0].stridew;i++) vga_state.vga_graphics_ram[i+blank_line_ofs] = 0;
-
-               sh = dh = gvar.video.page[0].height;
-               while (dh >= dh_step) {
-                       /* stop animating if the user hits ENTER */
-                       if (kbhit()) {
-                               if (getch() == 13) break;
-                       }
-
-                       /* wait for vsync end */
-                       vga_wait_for_vsync_end();
-
-                       /* what scalefactor to use for stretching? */
-                       ystep = (0x10000UL * sh) / dh;
-                       dstart = (gvar.video.page[0].height - dh) / 2; // center the squash effect on screen, otherwise it would squash to top of screen
-                       doh = display_ofs;
-                       soh = copy_ofs;
-                       yf = 0;
-                       y = 0;
-
-                       /* for performance, keep VGA in write mode 1 the entire render */
-                       vga_setup_wm1_block_copy();
-
-                       /* blank lines */
-                       if (dstart >= dh_blankfill) y = dstart - dh_blankfill;
-                       else y = 0;
-                       doh = gvar.video.page[0].stridew * y;
-
-                       while (y < dstart) {
-                               vga_wm1_mem_block_copy(doh,blank_line_ofs,gvar.video.page[0].stridew);
-                               doh += gvar.video.page[0].stridew;
-                               y++;
-                       }
-
-                       /* draw */
-                       while (y < (dh+dstart)) {
-                               soh = copy_ofs + ((yf >> 16UL) * gvar.video.page[0].stridew);
-                               vga_wm1_mem_block_copy(doh,soh,gvar.video.page[0].stridew);
-                               doh += gvar.video.page[0].stridew;
-                               yf += ystep;
-                               y++;
-                       }
-
-                       /* blank lines */
-                       while (y < gvar.video.page[0].height && y < (dh+dstart+dh_blankfill)) {
-                               vga_wm1_mem_block_copy(doh,blank_line_ofs,gvar.video.page[0].stridew);
-                               doh += gvar.video.page[0].stridew;
-                               y++;
-                       }
-
-                       /* done */
-                       vga_restore_rm0wm0();
-
-                       /* wait for vsync */
-                       vga_wait_for_vsync();
-
-                       /* make it shrink */
-                       dh -= dh_step;
-                       if (dh < 40) dh_step = 1;
-               }
-       }
-
-       IN_Shutdown();
-       VGAmodeX(0, 1, &gvar);
-       free(vrl_lineoffs);
-       buffer = NULL;
-       free(buffer);
-       bufsz = 0;
-       free(bakapee1);
-       free(bakapee2);
-       return 0;
-}
+#include <hw/cpu/cpu.h>\r
+#include <hw/dos/dos.h>\r
+#include <hw/vga/vga.h>\r
+#include <hw/vga/vrl.h>\r
+\r
+#include "src/tesuto.h"\r
+\r
+#define FILENAME_1 "data/aconita.vrl"\r
+#define FILENAME_2 "data/aconita.pal"\r
+\r
+static unsigned char palette[768];\r
+global_game_variables_t gvar;\r
+player_t player[1];\r
+\r
+int main(int argc,char **argv) {\r
+       struct vrl1_vgax_header *vrl_header;\r
+       vrl1_vgax_offset_t *vrl_lineoffs;\r
+       unsigned char *buffer;\r
+       unsigned int bufsz;\r
+       int fd;\r
+       char *bakapee1,*bakapee2;\r
+\r
+       bakapee1=malloc(64);\r
+       bakapee2=malloc(1024);\r
+\r
+       IN_Startup();\r
+       IN_Default(0,&player,ctrl_Joystick);\r
+       IN_initplayer(&player, 0);\r
+\r
+       if (argc < 3) {\r
+               fprintf(stderr,"drawvrl <VRL file> <palette file>\n");\r
+               bakapee1 = FILENAME_1;//"data/aconita.vrl";\r
+               bakapee2 = FILENAME_2;//"data/aconita.pal";\r
+               //return 1;\r
+       }else{\r
+               if(argv[1]) bakapee1 = argv[1];\r
+               if(argv[2]) bakapee2 = argv[2];\r
+       }\r
+\r
+       fd = open(bakapee1,O_RDONLY|O_BINARY);\r
+       if (fd < 0) {\r
+               fprintf(stderr,"Unable to open '%s'\n", bakapee1);\r
+               return 1;\r
+       }\r
+       {\r
+               unsigned long sz = lseek(fd,0,SEEK_END);\r
+               if (sz < sizeof(*vrl_header)) return 1;\r
+               if (sz >= 65535UL) return 1;\r
+\r
+               bufsz = (unsigned int)sz;\r
+               buffer = malloc(bufsz);\r
+               if (buffer == NULL) return 1;\r
+\r
+               lseek(fd,0,SEEK_SET);\r
+               if ((unsigned int)read(fd,buffer,bufsz) < bufsz) return 1;\r
+\r
+               vrl_header = (struct vrl1_vgax_header*)buffer;\r
+               if (memcmp(vrl_header->vrl_sig,"VRL1",4) || memcmp(vrl_header->fmt_sig,"VGAX",4)) return 1;\r
+               if (vrl_header->width == 0 || vrl_header->height == 0) return 1;\r
+       }\r
+       close(fd);\r
+\r
+       probe_dos();\r
+       if (!probe_vga()) {\r
+               printf("VGA probe failed\n");\r
+               return 1;\r
+       }\r
+       VGAmodeX(1, 1, &gvar);\r
+\r
+       /* load color palette */\r
+       fd = open(bakapee2,O_RDONLY|O_BINARY);\r
+       if (fd >= 0) {\r
+               unsigned int i;\r
+\r
+               read(fd,palette,768);\r
+               close(fd);\r
+\r
+               vga_palette_lseek(0);\r
+               for (i=0;i < 256;i++) vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);\r
+       }\r
+\r
+       /* preprocess the sprite to generate line offsets */\r
+       vrl_lineoffs = vrl1_vgax_genlineoffsets(vrl_header,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));\r
+       if (vrl_lineoffs == NULL) return 1;\r
+\r
+       /* setup camera and screen~ */\r
+       modexHiganbanaPageSetup(&gvar.video);\r
+       gvar.video.page[1].dx=gvar.video.page[0].dx=16;\r
+       gvar.video.page[1].dy=gvar.video.page[0].dy=16;\r
+       modexShowPage(&(gvar.video.page[0]));\r
+\r
+       #define VMEMHEIGHT gvar.video.page[0].height+gvar.video.page[1].height\r
+\r
+       //4     this dose the screen\r
+       {\r
+               unsigned int i,j,o;\r
+               /* fill screen with a distinctive pattern */\r
+               for (i=0;i < gvar.video.page[0].width;i++) {\r
+                       o = i >> 2;\r
+                       vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
+                       for (j=0;j < VMEMHEIGHT;j++,o += gvar.video.page[0].stridew)\r
+                               vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
+               }\r
+       }\r
+\r
+       //while (getch() != 13);\r
+\r
+       /* make distinctive pattern offscreen, render sprite, copy onscreen.\r
+        * this time, we render the distinctive pattern to another offscreen location and just copy.\r
+        * note this version is much faster too! */\r
+       {\r
+               unsigned int i,j,o,o2;\r
+               int x,y,rx,ry,w,h;\r
+               unsigned int overdraw = 1;      // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks.\r
+                                               // if the sprite's edge pixels are clear anyway, you can set this to 0.\r
+               VGA_RAM_PTR omemptr;\r
+               int xdir=1,ydir=1;\r
+\r
+               //4     this dose the sprite? wwww\r
+               /* fill pattern offset with a distinctive pattern */\r
+               for (i=0;i < gvar.video.page[0].width;i++) {\r
+                       o = (i >> 2) + (0x10000UL - (uint16_t)gvar.video.page[1].data);\r
+                       vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
+                       for (j=0;j < VMEMHEIGHT;j++,o += gvar.video.page[0].stridew)\r
+                               vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
+               }\r
+\r
+               /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */\r
+               x = 0;\r
+               y = 0;\r
+\r
+               /* do it */\r
+               omemptr = vga_state.vga_graphics_ram; // save original mem ptr\r
+\r
+               while(!IN_KeyDown(sc_Escape))\r
+               {\r
+                       IN_ReadControl(0,&player);\r
+                       if(IN_KeyDown(2)) modexShowPage(&(gvar.video.page[0]));\r
+                       if(IN_KeyDown(3)) modexShowPage(&(gvar.video.page[1]));\r
+                       if(IN_KeyDown(68))      //f10\r
+                       {\r
+                               //gvar.kurokku.fpscap=!gvar.kurokku.fpscap;\r
+                               IN_UserInput(1,1);\r
+                       }\r
+\r
+                       /* render box bounds. y does not need modification, but x and width must be multiple of 4 */\r
+                       if (x >= overdraw) rx = (x - overdraw) & (~3);\r
+                       else rx = -(gvar.video.page[0].dx);\r
+                       if (y >= overdraw) ry = (y - overdraw);\r
+                       else ry = -(gvar.video.page[0].dy);\r
+                       h = vrl_header->height + overdraw + y - ry;\r
+                       w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3);\r
+                       if ((rx+w) > gvar.video.page[0].width) w = gvar.video.page[0].width-rx;\r
+                       if ((ry+h) > gvar.video.page[0].height) h = (gvar.video.page[0].height)-ry;\r
+\r
+                       /* block copy pattern to where we will draw the sprite */\r
+                       vga_setup_wm1_block_copy();\r
+                       o2 = gvar.video.page[0].pagesize;\r
+                       o = (0x10000UL - (uint16_t)gvar.video.page[1].data) + (ry * gvar.video.page[0].stridew) + (rx >> 2); // source offscreen\r
+                       for (i=0;i < h;i++,o += gvar.video.page[0].stridew,o2 += (w >> 2)) vga_wm1_mem_block_copy(o2,o,w >> 2);\r
+                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */\r
+                       vga_restore_rm0wm0();\r
+\r
+                       /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */\r
+                       vga_state.vga_draw_stride_limit = (gvar.video.page[0].width + 3/*round up*/ - x) >> 2;\r
+                       vga_state.vga_draw_stride = w >> 2;\r
+                       vga_state.vga_graphics_ram = omemptr + gvar.video.page[0].pagesize;\r
+\r
+                       /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */\r
+                       draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));\r
+\r
+                       /* restore ptr */\r
+                       vga_state.vga_graphics_ram = omemptr;\r
+\r
+                       /* block copy to visible RAM from offscreen */\r
+                       vga_setup_wm1_block_copy();\r
+                       o = gvar.video.page[0].pagesize; // source offscreen\r
+                       o2 = (ry * gvar.video.page[0].stridew) + (rx >> 2); // dest visible (original stride)\r
+                       for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += gvar.video.page[0].stridew) vga_wm1_mem_block_copy(o2,o,w >> 2);\r
+                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */\r
+                       vga_restore_rm0wm0();\r
+\r
+                       /* restore stride */\r
+                       vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = gvar.video.page[0].stridew;\r
+\r
+                       /* step */\r
+                       x += xdir; y += ydir;\r
+                       if ((x + vrl_header->width) >= ((gvar.video.page[0].width + gvar.video.page[0].dx) - 1) || x == -(gvar.video.page[0].dx))\r
+                               xdir = -xdir;\r
+                       if ((y + vrl_header->height) >= ((gvar.video.page[0].height + gvar.video.page[0].dy) - 1) || y == -(gvar.video.page[0].dy))\r
+                               ydir = -ydir;\r
+                       //printf("[x%u y%u]     [rx%u ry%u]             [w%u h%u]\n", x, y, rx, ry, w, h);\r
+               }\r
+       }\r
+\r
+       IN_UserInput(1,1);\r
+\r
+       while(!IN_KeyDown(sc_Escape))\r
+       {\r
+               if(IN_KeyDown(2)) modexShowPage(&(gvar.video.page[0]));\r
+               if(IN_KeyDown(3)) modexShowPage(&(gvar.video.page[1]));\r
+       }\r
+\r
+       modexShowPage(&(gvar.video.page[0]));\r
+       /* another handy "demo" effect using VGA write mode 1.\r
+        * we can take what's on screen and vertically squash it like an old analog TV set turning off. */\r
+       {\r
+               unsigned int blank_line_ofs = (gvar.video.page[0].stridew * gvar.video.page[0].height * 2);\r
+               unsigned int copy_ofs = (gvar.video.page[0].stridew * gvar.video.page[0].height);\r
+               unsigned int display_ofs = 0x0000;\r
+               unsigned int i,y,soh,doh,dstart;\r
+               unsigned int dh_blankfill = 8;\r
+               unsigned int dh_step = 8;\r
+               uint32_t sh,dh,yf,ystep;\r
+\r
+               /* copy active display (0) to offscreen buffer (0x4000) */\r
+               vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = gvar.video.page[0].stridew;\r
+               vga_setup_wm1_block_copy();\r
+               vga_wm1_mem_block_copy(copy_ofs,display_ofs,gvar.video.page[0].stridew * gvar.video.page[0].height);\r
+               vga_restore_rm0wm0();\r
+\r
+               /* need a blank line as well */\r
+               for (i=0;i < gvar.video.page[0].stridew;i++) vga_state.vga_graphics_ram[i+blank_line_ofs] = 0;\r
+\r
+               sh = dh = gvar.video.page[0].height;\r
+               while (dh >= dh_step) {\r
+                       /* stop animating if the user hits ENTER */\r
+                       if (kbhit()) {\r
+                               if (getch() == 13) break;\r
+                       }\r
+\r
+                       /* wait for vsync end */\r
+                       vga_wait_for_vsync_end();\r
+\r
+                       /* what scalefactor to use for stretching? */\r
+                       ystep = (0x10000UL * sh) / dh;\r
+                       dstart = (gvar.video.page[0].height - dh) / 2; // center the squash effect on screen, otherwise it would squash to top of screen\r
+                       doh = display_ofs;\r
+                       soh = copy_ofs;\r
+                       yf = 0;\r
+                       y = 0;\r
+\r
+                       /* for performance, keep VGA in write mode 1 the entire render */\r
+                       vga_setup_wm1_block_copy();\r
+\r
+                       /* blank lines */\r
+                       if (dstart >= dh_blankfill) y = dstart - dh_blankfill;\r
+                       else y = 0;\r
+                       doh = gvar.video.page[0].stridew * y;\r
+\r
+                       while (y < dstart) {\r
+                               vga_wm1_mem_block_copy(doh,blank_line_ofs,gvar.video.page[0].stridew);\r
+                               doh += gvar.video.page[0].stridew;\r
+                               y++;\r
+                       }\r
+\r
+                       /* draw */\r
+                       while (y < (dh+dstart)) {\r
+                               soh = copy_ofs + ((yf >> 16UL) * gvar.video.page[0].stridew);\r
+                               vga_wm1_mem_block_copy(doh,soh,gvar.video.page[0].stridew);\r
+                               doh += gvar.video.page[0].stridew;\r
+                               yf += ystep;\r
+                               y++;\r
+                       }\r
+\r
+                       /* blank lines */\r
+                       while (y < gvar.video.page[0].height && y < (dh+dstart+dh_blankfill)) {\r
+                               vga_wm1_mem_block_copy(doh,blank_line_ofs,gvar.video.page[0].stridew);\r
+                               doh += gvar.video.page[0].stridew;\r
+                               y++;\r
+                       }\r
+\r
+                       /* done */\r
+                       vga_restore_rm0wm0();\r
+\r
+                       /* wait for vsync */\r
+                       vga_wait_for_vsync();\r
+\r
+                       /* make it shrink */\r
+                       dh -= dh_step;\r
+                       if (dh < 40) dh_step = 1;\r
+               }\r
+       }\r
+\r
+       IN_Shutdown();\r
+       VGAmodeX(0, 1, &gvar);\r
+       free(vrl_lineoffs);\r
+       buffer = NULL;\r
+       free(buffer);\r
+       bufsz = 0;\r
+       free(bakapee1);\r
+       free(bakapee2);\r
+       return 0;\r
+}\r
index 60043f41f2daac292baec37fe1791ac73aa20ef1..faba5120b37e0eda5cec750f6c58f1d9b85f1e6d 100755 (executable)
@@ -1,8 +1,8 @@
-# SciTE session file
-
-buffer.1.path=/dos/z/16/src/16.c
-buffer.1.position=1
-
-buffer.2.path=/dos/z/16/src/16.h
-buffer.2.position=1
-buffer.2.current=1
+# SciTE session file\r
+\r
+buffer.1.path=/dos/z/16/src/16.c\r
+buffer.1.position=1\r
+\r
+buffer.2.path=/dos/z/16/src/16.h\r
+buffer.2.position=1\r
+buffer.2.current=1\r
index 5a16247dc77b08733c6dead71510d6650c4d88d6..0db48708670fa5c9ce751da0e65728666f605992 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "src/lib/scroll16.h"
-#include "src/lib/16_timer.h"
-#include "src/lib/wcpu/wcpu.h"
-#include "src/lib/16_sprite.h"
-#include "src/lib/16_ca.h"
-#include "src/lib/16_mm.h"
-//#include "src/lib/16_head.h"//included already
-
-//#define FADE
-#define MODEX  //this is for mode x initiating
-
-//word far *clock= (word far*) 0x046C; /* 18.2hz clock */
-//bitmap_t *p;
-global_game_variables_t gvar;
-static map_t map;
-player_t player[MaxPlayers];
-map_view_t mv[4];
-byte *ppal;
-//word pn=0; //i forgot ww
-float t;
-sword bakapee;
-pan_t pan;
-//debugswitches
-boolean panswitch=0;
-//extern boolean pageflipflop=1;
-       unsigned int i;
-       const char *cpus;
-       //static int persist_aniframe = 0;    /* gonna be increased to 1 before being used, so 0 is ok for default */
-
-       //map_view_db_t pgid[4];
-       word pg;
-//#ifdef FADE
-       static word paloffset=0;
-       byte *dpal;
-//#endif
-       byte *gpal;
-       byte *ptr;
-       byte *mappalptr;
-
-void main(int argc, char *argv[])
-{
-       struct sprite sp;
-       __segment sega;
-       void __based(sega)* bigbuffer;
-
-       byte *mesg=malloc(sizeof(dword));
-       int i;
-
-       if(argv[1]) bakapee = atoi(argv[1]);
-       else bakapee = 1;
-
-       gvar.mm.mmstarted=0;
-       gvar.bigbuffer=bigbuffer;
-
-       MM_Startup(&gvar.mm, &gvar.mmi);
-       CA_Startup(&gvar);
-       // DOSLIB: check our environment
-       probe_dos();
-
-       // DOSLIB: what CPU are we using?
-       // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS.
-       //      So this code by itself shouldn't care too much what CPU it's running on. Except that other
-       //      parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for
-       //      the CPU to carry out tasks. --J.C.
-       cpu_probe();
-
-       // DOSLIB: check for VGA
-       if (!probe_vga()) {
-               printf("VGA probe failed\n");
-               return;
-       }
-       // hardware must be VGA or higher!
-       if (!(vga_state.vga_flags & VGA_IS_VGA)) {
-               printf("This program requires VGA or higher graphics hardware\n");
-               return;
-       }
-
-       if (_DEBUG_INIT() == 0) {
-#ifdef DEBUGSERIAL
-               printf("WARNING: Failed to initialize DEBUG output\n");
-#endif
-       }
-       _DEBUG("Serial debug output started\n"); // NTS: All serial output must end messages with newline, or DOSBox-X will not emit text to log
-       _DEBUGF("Serial debug output printf test %u %u %u\n",1U,2U,3U);
-
-       pan.pn=1;
-
-       start_timer(&gvar);
-
-       /* create the map */
-       fprintf(stderr, "testing map load~      ");
-       loadmap("data/test.map", &map);
-       chkmap(&map, 0);
-       printf("chkmap ok       ");
-       fprintf(stderr, "yay map loaded~~\n");
-
-       /* draw the tiles */
-#ifdef MODEX
-       ptr = map.data;
-
-       /* data */
-       i = read_vrs(&gvar, "data/spri/chikyuu.vrs", sp.spritesheet);
-       if (i)
-       {
-               puts("Error! Did not load sprite!");
-               return;
-       }
-       puts("Sprite should be loaded now");
-       putch('q');
-       print_anim_ids(&sp);
-       putch('r');
-       i = set_anim_by_id(&sp, 10);
-       if (i == -1)
-       {
-               printf("Anim id not found!");
-               return;
-       }
-/*     player[0].spri = malloc(...)
- *     read_vrs(&gvar, "data/spri/chikyuu.vrs", player[0].spri->spritesheet); // load sprite
-       putch('s');
-       print_anim_ids(player[0].spri);
-       putch('t');
-       i = set_anim_by_id(player[0].spri, 10);
-       if (i == -1)
-       {
-               printf("Anim id not found!");
-               return;
-       }*/
-       player[0].spri = &sp;
-
-#endif
-       /*      input!  */
-       IN_Startup();
-       IN_Default(0,&player,ctrl_Joystick);
-
-       /* save the palette */
-#ifdef MODEX
-#ifdef FADE
-       dpal = modexNewPal();
-       modexPalSave(dpal);
-       modexFadeOff(4, dpal);
-#endif
-
-       textInit();
-       VGAmodeX(bakapee, 1, &gvar);
-#ifdef FADE
-       modexPalBlack();        //reset the palette~
-#endif
-#endif
-       modexLoadPalFile("data/spri/chikyuu.pal", &ppal);
-       modexPalUpdate1(ppal);
-#ifdef MODEX
-#ifdef FADE
-       gpal = modexNewPal();
-       modexPalSave(gpal);
-       modexSavePalFile("data/g.pal", gpal);
-       modexPalBlack();        //so player will not see loadings~
-#endif
-#endif
-
-       /* setup camera and screen~ */
-       modexHiganbanaPageSetup(&gvar.video);
-       for(i=0;i<gvar.video.num_of_pages;i++)
-       {
-               mv[i].page = &gvar.video.page[i];
-               mv[i].map = &map;
-               mv[i].video = &gvar.video;
-               mv[i].pan       = &pan;
-       }
-
-       /* set up paging */
-       //TODO: LOAD map data and position the map in the middle of the screen if smaller then screen
-       mapGoTo(mv, 0, 0);
-       //_fmemcpy(mv[1].page->data, mv[0].page->data, mv[0].page->pagesize);
-
-       //TODO: put player in starting position of spot
-       //default player position on the viewable map
-       player[0].tx = mv[0].tx + mv[0].page->tilemidposscreenx;
-       player[0].ty = mv[0].ty + mv[0].page->tilemidposscreeny;
-       IN_initplayer(&player, 0);
-       //IN_initplayer(&player, 1);
-
-#ifndef        SPRITE
-       modexClearRegion(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);
-       //modexClearRegion(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);
-#else
-       //PBUFSFUN(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 64, 24, 32, PLAYERBMPDATA);
-       //PBUFSFUN(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 64, 16, 32, player[0].data);
-       animate_spri(player[0].spri);
-#endif
-
-       if(!pageflipflop)       modexShowPage(mv[1].page);
-       else                    modexShowPage(mv[0].page);//!(gvar.video.p)
-               shinku_fps_indicator_page = 0; // we're on page 1 now, shinku(). follow along please or it will not be visible.
-
-       /* buffer pages */
-//     modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 47);
-//     modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 45);
-//     {
-//             unsigned int k,j,o;
-//             /* fill screen with a distinctive pattern */
-//             for (k=0;k < vga_state.vga_width;k++) {
-//                     o = k >> 2;
-//                     vga_write_sequencer(0x02/*map mask*/,1 << (k&3));
-//                             for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride)
-//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!
-//             }
-//     }
-       modexClearRegion(mv[3].page, 0, 128, 24, 36, 15);
-
-#ifdef MODEX
-#ifdef FADE
-       modexFadeOn(4, gpal);
-#endif
-#endif
-       while(!IN_KeyDown(sc_Escape) && player[0].hp>0)
-       {
-               shinku(&gvar);
-       //top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square
-       //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction
-       //when player[0].tx or player[0].ty == 0 or player[0].tx == 20 or player[0].ty == 15 then stop because that is edge of map and you do not want to walk of the map
-
-       //player movement
-               IN_ReadControl(0,&player);
-       if(!panswitch){
-               walk(mv, player, 0);
-       }else{
-               panpagemanual(mv, player, 0);
-               //printf("      player[0].q: %d", player[0].q); printf("        player[0].d: %d\n", player[0].d);
-       }
-
-       //the scripting stuff....
-       //if(((player[0].triggerx == TRIGGX && player[0].triggery == TRIGGY) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))
-       if(((mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))] == 0) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))
-       {
-               short i;
-               for(i=800; i>=400; i--)
-               {
-                       sound(i);
-               }
-               nosound();
-       }
-       if(player[0].q == (TILEWH/(player[0].speed))+1 && player[0].info.dir != 2 && (player[0].triggerx == 5 && player[0].triggery == 5)){ player[0].hp--; }
-       //debugging binds!
-       if(IN_KeyDown(2)){ modexShowPage(mv[0].page); pan.pn=0; }
-       if(IN_KeyDown(3)){ modexShowPage(mv[1].page); pan.pn=1; }
-       if(IN_KeyDown(4)){ modexShowPage(mv[2].page); pan.pn=2; }
-       if(IN_KeyDown(4+1)){ modexShowPage(mv[3].page); pan.pn=3; }
-       if(IN_KeyDown(25)){ modexpdump(mv[0].page); modexpdump(mv[1].page);
-                IN_UserInput(1,1);
-       }       //p
-#ifdef MODEX
-#ifdef FADE
-       if(IN_KeyDown(24)){ modexPalUpdate0(gpal); paloffset=0; modexpdump(mv[0].page); modexpdump(mv[1].page);  IN_UserInput(1,1); }
-       if(IN_KeyDown(22)){
-//     paloffset=0; modexPalBlack(); modexPalUpdate(player[0].data, &paloffset, 0, 0);
-//     printf("1paloffset      =       %d\n", paloffset/3);
-//      modexPalUpdate(map.tiles->data, &paloffset, 0, 0);
-//     printf("2paloffset      =       %d\n", paloffset/3);
-//      modexpdump(mv[0].page); modexpdump(mv[1].page);
-               IN_UserInput(1,1);
-       }
-#endif
-#endif
-       //pan switch
-       if(IN_KeyDown(88)){panswitch=!panswitch; IN_UserInput(1,1);}    //f12
-       if(IN_KeyDown(87))      //f11
-       {
-               pageflipflop=!pageflipflop;
-               IN_UserInput(1,1);
-//             VGAmodeX(0, 0, &gvar);
-//             IN_Shutdown();
-//             __asm
-//             {
-//                     mov ah,31h
-//                     int 21h
-//             }
-       }
-       if(IN_KeyDown(68))      //f10
-       {
-               gvar.kurokku.fpscap=!gvar.kurokku.fpscap;
-               IN_UserInput(1,1);
-       }
-       if(IN_KeyDown(67))      //f9
-       {
-               modexClearRegion(mv[1].page, 0, 0, mv[1].page->width, mv[1].page->height, 2);
-               modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 3);
-               modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 4);
-               modexClearRegion(mv[3].page, 0, 0, 20, 36, 15);
-               //IN_UserInput(1,1);
-       }
-       if(IN_KeyDown(66))      //f8
-       {
-//             modexDrawSprite(mv[0].page, 16, 16, p);
-//             modexDrawSprite(mv[0].page, 32+48, 16, (player[0].data));
-       }
-       //TODO fmemtest into page
-       /*if(IN_KeyDown(4+1))   //4
-       {
-               pg=1;
-               SELECT_ALL_PLANES();
-               _fmemset(((mv[pg].page->data+4)+(16*(mv[pg].page->width/4))), 15, 4);
-       }*/
-
-       //9
-       if(IN_KeyDown(10)){ modexPalOverscan(rand()%56); modexPalUpdate1(dpal); IN_UserInput(1,1); }
-       //if(IN_KeyDown(11)){ modexPalOverscan(15); }
-       if((player[0].q==1) && !(player[0].x%TILEWH==0 && player[0].y%TILEWH==0)) break;        //incase things go out of sync!
-       }
-
-       /* fade back to text mode */
-       /* but 1st lets save the game palette~ */
-#ifdef MODEX
-#ifdef FADE
-       modexPalSave(gpal);
-       modexSavePalFile("data/g.pal", gpal);
-       modexFadeOff(4, gpal);
-#endif
-       VGAmodeX(0, 1, &gvar);
-#endif
-       IN_Shutdown();
-       MM_FreePtr(&bigbuffer, &gvar.mm);
-       CA_Shutdown(&gvar);
-       MM_Shutdown(&gvar.mm);
-       printf("\nProject 16 scroll.exe. This is just a test file!\n");
-       printf("version %s\n", VERSION);
-       printf("tx: %d  ", mv[0].tx);
-       printf("ty: %d\n", mv[0].ty);
-       printf("\n");
-       printf("player vars:\n");
-       printf("        x: %d", player[0].x); printf("  y: %d\n", player[0].y);
-       //if(player[0].hp==0) printf("%d wwww\n", player[0].y+8);
-       //else printf("\nplayer[0].y: %d\n", player[0].y);
-       printf("        tx: %d", player[0].tx); printf("        ty: %d\n", player[0].ty);
-       printf("        triggx: %d", player[0].triggerx); printf("      triggy: %d\n", player[0].triggery);
-       printf("        hp: %d", (player[0].hp));       printf("        q: %d", player[0].q);   printf("        player.info.dir: %d", player[0].info.dir);      printf("        player.d: %d ", player[0].d);
-               printf("        pdir=%d\n", player[0].pdir);
-       printf("        tile data value at player trigger position: %d\n\n", mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))]);
-//     printf("palette offset: %d\n", paloffset/3);
-//++++ printf("Total used: %zu\n", oldfreemem-GetFreeSize());
-//++++ printf("Total free: %zu\n", GetFreeSize());
-//not used now printf("temporary player sprite 0: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=45556867\n");
-//not used now printf("temporary player sprite 1: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=44606385\n");
-       printf("Virtual Screen: %dx", gvar.video.page[0].width);        printf("%d      ", gvar.video.page[0].height);
-       printf("Screen: %dx", gvar.video.page[0].sw);   printf("%d\n", gvar.video.page[0].sh);
-       printf("virtual tile resolution: %dx", gvar.video.page[0].tilesw);      printf("%d      ", gvar.video.page[0].tilesh);
-       printf("tile resolution: %dx", gvar.video.page[0].tw);  printf("%d\n", gvar.video.page[0].th);
-       printf("middle tile position: %dx", gvar.video.page[0].tilemidposscreenx);      printf("%d\n", gvar.video.page[0].tilemidposscreeny);
-       modexprintmeminfo(&gvar.video);
-       //printf("mv[%u].tx: %d", pan.pn, mv[pan.pn].tx); printf("      mv[%u].ty: %d   ", pan.pn, mv[pan.pn].ty);
-       printf("gvar.video.p=%u ", gvar.video.p); printf("gvar.video.r=%u ", gvar.video.r);
-       printf("pageflipflop=%u\n", pageflipflop);
-       //0000printf("\ngvar.video.tickclk=%f\n", gvar.video.tickclk);
-       //0000printf("gvar.video.clk=%f", gvar.video.clk);
-       printf("\n");
-       //printf("map.width=%d  map.height=%d   map.data[0]=%d\n", mv[0].map->width, mv[0].map->height, mv[0].map->data[0]);
-
-       printf("\n");
-       switch(detectcpu())
-       {
-               case 0: cpus = "8086/8088 or 186/88"; break;
-               case 1: cpus = "286"; break;
-               case 2: cpus = "386 or newer"; break;
-               default: cpus = "internal error"; break;
-       }
-       printf("detected CPU type: %s\n", cpus);
-#ifdef MODEX
-#ifdef FADE
-       modexFadeOn(4, dpal);
-#endif
-#endif
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "src/lib/scroll16.h"\r
+#include "src/lib/16_timer.h"\r
+#include "src/lib/wcpu/wcpu.h"\r
+#include "src/lib/16_sprite.h"\r
+#include "src/lib/16_ca.h"\r
+#include "src/lib/16_mm.h"\r
+//#include "src/lib/16_head.h"//included already\r
+\r
+//#define FADE\r
+#define MODEX  //this is for mode x initiating\r
+\r
+//word far *clock= (word far*) 0x046C; /* 18.2hz clock */\r
+//bitmap_t *p;\r
+global_game_variables_t gvar;\r
+static map_t map;\r
+player_t player[MaxPlayers];\r
+map_view_t mv[4];\r
+byte *ppal;\r
+//word pn=0; //i forgot ww\r
+float t;\r
+sword bakapee;\r
+pan_t pan;\r
+//debugswitches\r
+boolean panswitch=0;\r
+//extern boolean pageflipflop=1;\r
+       unsigned int i;\r
+       const char *cpus;\r
+       //static int persist_aniframe = 0;    /* gonna be increased to 1 before being used, so 0 is ok for default */\r
+\r
+       //map_view_db_t pgid[4];\r
+       word pg;\r
+//#ifdef FADE\r
+       static word paloffset=0;\r
+       byte *dpal;\r
+//#endif\r
+       byte *gpal;\r
+       byte *ptr;\r
+       byte *mappalptr;\r
+\r
+void main(int argc, char *argv[])\r
+{\r
+       struct sprite sp;\r
+       __segment sega;\r
+       void __based(sega)* bigbuffer;\r
+\r
+       byte *mesg=malloc(sizeof(dword));\r
+       int i;\r
+\r
+       if(argv[1]) bakapee = atoi(argv[1]);\r
+       else bakapee = 1;\r
+\r
+       gvar.mm.mmstarted=0;\r
+       gvar.bigbuffer=bigbuffer;\r
+\r
+       MM_Startup(&gvar.mm, &gvar.mmi);\r
+       CA_Startup(&gvar);\r
+       // DOSLIB: check our environment\r
+       probe_dos();\r
+\r
+       // DOSLIB: what CPU are we using?\r
+       // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS.\r
+       //      So this code by itself shouldn't care too much what CPU it's running on. Except that other\r
+       //      parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for\r
+       //      the CPU to carry out tasks. --J.C.\r
+       cpu_probe();\r
+\r
+       // DOSLIB: check for VGA\r
+       if (!probe_vga()) {\r
+               printf("VGA probe failed\n");\r
+               return;\r
+       }\r
+       // hardware must be VGA or higher!\r
+       if (!(vga_state.vga_flags & VGA_IS_VGA)) {\r
+               printf("This program requires VGA or higher graphics hardware\n");\r
+               return;\r
+       }\r
+\r
+       if (_DEBUG_INIT() == 0) {\r
+#ifdef DEBUGSERIAL\r
+               printf("WARNING: Failed to initialize DEBUG output\n");\r
+#endif\r
+       }\r
+       _DEBUG("Serial debug output started\n"); // NTS: All serial output must end messages with newline, or DOSBox-X will not emit text to log\r
+       _DEBUGF("Serial debug output printf test %u %u %u\n",1U,2U,3U);\r
+\r
+       pan.pn=1;\r
+\r
+       start_timer(&gvar);\r
+\r
+       /* create the map */\r
+       fprintf(stderr, "testing map load~      ");\r
+       loadmap("data/test.map", &map);\r
+       chkmap(&map, 0);\r
+       printf("chkmap ok       ");\r
+       fprintf(stderr, "yay map loaded~~\n");\r
+\r
+       /* draw the tiles */\r
+#ifdef MODEX\r
+       ptr = map.data;\r
+\r
+       /* data */\r
+       i = read_vrs(&gvar, "data/spri/chikyuu.vrs", sp.spritesheet);\r
+       if (i)\r
+       {\r
+               puts("Error! Did not load sprite!");\r
+               return;\r
+       }\r
+       puts("Sprite should be loaded now");\r
+       putch('q');\r
+       print_anim_ids(&sp);\r
+       putch('r');\r
+       i = set_anim_by_id(&sp, 10);\r
+       if (i == -1)\r
+       {\r
+               printf("Anim id not found!");\r
+               return;\r
+       }\r
+/*     player[0].spri = malloc(...)\r
+ *     read_vrs(&gvar, "data/spri/chikyuu.vrs", player[0].spri->spritesheet); // load sprite\r
+       putch('s');\r
+       print_anim_ids(player[0].spri);\r
+       putch('t');\r
+       i = set_anim_by_id(player[0].spri, 10);\r
+       if (i == -1)\r
+       {\r
+               printf("Anim id not found!");\r
+               return;\r
+       }*/\r
+       player[0].spri = &sp;\r
+\r
+#endif\r
+       /*      input!  */\r
+       IN_Startup();\r
+       IN_Default(0,&player,ctrl_Joystick);\r
+\r
+       /* save the palette */\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       dpal = modexNewPal();\r
+       modexPalSave(dpal);\r
+       modexFadeOff(4, dpal);\r
+#endif\r
+\r
+       textInit();\r
+       VGAmodeX(bakapee, 1, &gvar);\r
+#ifdef FADE\r
+       modexPalBlack();        //reset the palette~\r
+#endif\r
+#endif\r
+       modexLoadPalFile("data/spri/chikyuu.pal", &ppal);\r
+       modexPalUpdate1(ppal);\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       gpal = modexNewPal();\r
+       modexPalSave(gpal);\r
+       modexSavePalFile("data/g.pal", gpal);\r
+       modexPalBlack();        //so player will not see loadings~\r
+#endif\r
+#endif\r
+\r
+       /* setup camera and screen~ */\r
+       modexHiganbanaPageSetup(&gvar.video);\r
+       for(i=0;i<gvar.video.num_of_pages;i++)\r
+       {\r
+               mv[i].page = &gvar.video.page[i];\r
+               mv[i].map = &map;\r
+               mv[i].video = &gvar.video;\r
+               mv[i].pan       = &pan;\r
+       }\r
+\r
+       /* set up paging */\r
+       //TODO: LOAD map data and position the map in the middle of the screen if smaller then screen\r
+       mapGoTo(mv, 0, 0);\r
+       //_fmemcpy(mv[1].page->data, mv[0].page->data, mv[0].page->pagesize);\r
+\r
+       //TODO: put player in starting position of spot\r
+       //default player position on the viewable map\r
+       player[0].tx = mv[0].tx + mv[0].page->tilemidposscreenx;\r
+       player[0].ty = mv[0].ty + mv[0].page->tilemidposscreeny;\r
+       IN_initplayer(&player, 0);\r
+       //IN_initplayer(&player, 1);\r
+\r
+#ifndef        SPRITE\r
+       modexClearRegion(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);\r
+       //modexClearRegion(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);\r
+#else\r
+       //PBUFSFUN(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 64, 24, 32, PLAYERBMPDATA);\r
+       //PBUFSFUN(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 64, 16, 32, player[0].data);\r
+       animate_spri(player[0].spri);\r
+#endif\r
+\r
+       if(!pageflipflop)       modexShowPage(mv[1].page);\r
+       else                    modexShowPage(mv[0].page);//!(gvar.video.p)\r
+               shinku_fps_indicator_page = 0; // we're on page 1 now, shinku(). follow along please or it will not be visible.\r
+\r
+       /* buffer pages */\r
+//     modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 47);\r
+//     modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 45);\r
+//     {\r
+//             unsigned int k,j,o;\r
+//             /* fill screen with a distinctive pattern */\r
+//             for (k=0;k < vga_state.vga_width;k++) {\r
+//                     o = k >> 2;\r
+//                     vga_write_sequencer(0x02/*map mask*/,1 << (k&3));\r
+//                             for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride)\r
+//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!\r
+//             }\r
+//     }\r
+       modexClearRegion(mv[3].page, 0, 128, 24, 36, 15);\r
+\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       modexFadeOn(4, gpal);\r
+#endif\r
+#endif\r
+       while(!IN_KeyDown(sc_Escape) && player[0].hp>0)\r
+       {\r
+               shinku(&gvar);\r
+       //top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square\r
+       //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction\r
+       //when player[0].tx or player[0].ty == 0 or player[0].tx == 20 or player[0].ty == 15 then stop because that is edge of map and you do not want to walk of the map\r
+\r
+       //player movement\r
+               IN_ReadControl(0,&player);\r
+       if(!panswitch){\r
+               walk(mv, player, 0);\r
+       }else{\r
+               panpagemanual(mv, player, 0);\r
+               //printf("      player[0].q: %d", player[0].q); printf("        player[0].d: %d\n", player[0].d);\r
+       }\r
+\r
+       //the scripting stuff....\r
+       //if(((player[0].triggerx == TRIGGX && player[0].triggery == TRIGGY) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))\r
+       if(((mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))] == 0) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))\r
+       {\r
+               short i;\r
+               for(i=800; i>=400; i--)\r
+               {\r
+                       sound(i);\r
+               }\r
+               nosound();\r
+       }\r
+       if(player[0].q == (TILEWH/(player[0].speed))+1 && player[0].info.dir != 2 && (player[0].triggerx == 5 && player[0].triggery == 5)){ player[0].hp--; }\r
+       //debugging binds!\r
+       if(IN_KeyDown(2)){ modexShowPage(mv[0].page); pan.pn=0; }\r
+       if(IN_KeyDown(3)){ modexShowPage(mv[1].page); pan.pn=1; }\r
+       if(IN_KeyDown(4)){ modexShowPage(mv[2].page); pan.pn=2; }\r
+       if(IN_KeyDown(4+1)){ modexShowPage(mv[3].page); pan.pn=3; }\r
+       if(IN_KeyDown(25)){ modexpdump(mv[0].page); modexpdump(mv[1].page);\r
+                IN_UserInput(1,1);\r
+       }       //p\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       if(IN_KeyDown(24)){ modexPalUpdate0(gpal); paloffset=0; modexpdump(mv[0].page); modexpdump(mv[1].page);  IN_UserInput(1,1); }\r
+       if(IN_KeyDown(22)){\r
+//     paloffset=0; modexPalBlack(); modexPalUpdate(player[0].data, &paloffset, 0, 0);\r
+//     printf("1paloffset      =       %d\n", paloffset/3);\r
+//      modexPalUpdate(map.tiles->data, &paloffset, 0, 0);\r
+//     printf("2paloffset      =       %d\n", paloffset/3);\r
+//      modexpdump(mv[0].page); modexpdump(mv[1].page);\r
+               IN_UserInput(1,1);\r
+       }\r
+#endif\r
+#endif\r
+       //pan switch\r
+       if(IN_KeyDown(88)){panswitch=!panswitch; IN_UserInput(1,1);}    //f12\r
+       if(IN_KeyDown(87))      //f11\r
+       {\r
+               pageflipflop=!pageflipflop;\r
+               IN_UserInput(1,1);\r
+//             VGAmodeX(0, 0, &gvar);\r
+//             IN_Shutdown();\r
+//             __asm\r
+//             {\r
+//                     mov ah,31h\r
+//                     int 21h\r
+//             }\r
+       }\r
+       if(IN_KeyDown(68))      //f10\r
+       {\r
+               gvar.kurokku.fpscap=!gvar.kurokku.fpscap;\r
+               IN_UserInput(1,1);\r
+       }\r
+       if(IN_KeyDown(67))      //f9\r
+       {\r
+               modexClearRegion(mv[1].page, 0, 0, mv[1].page->width, mv[1].page->height, 2);\r
+               modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 3);\r
+               modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 4);\r
+               modexClearRegion(mv[3].page, 0, 0, 20, 36, 15);\r
+               //IN_UserInput(1,1);\r
+       }\r
+       if(IN_KeyDown(66))      //f8\r
+       {\r
+//             modexDrawSprite(mv[0].page, 16, 16, p);\r
+//             modexDrawSprite(mv[0].page, 32+48, 16, (player[0].data));\r
+       }\r
+       //TODO fmemtest into page\r
+       /*if(IN_KeyDown(4+1))   //4\r
+       {\r
+               pg=1;\r
+               SELECT_ALL_PLANES();\r
+               _fmemset(((mv[pg].page->data+4)+(16*(mv[pg].page->width/4))), 15, 4);\r
+       }*/\r
+\r
+       //9\r
+       if(IN_KeyDown(10)){ modexPalOverscan(rand()%56); modexPalUpdate1(dpal); IN_UserInput(1,1); }\r
+       //if(IN_KeyDown(11)){ modexPalOverscan(15); }\r
+       if((player[0].q==1) && !(player[0].x%TILEWH==0 && player[0].y%TILEWH==0)) break;        //incase things go out of sync!\r
+       }\r
+\r
+       /* fade back to text mode */\r
+       /* but 1st lets save the game palette~ */\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       modexPalSave(gpal);\r
+       modexSavePalFile("data/g.pal", gpal);\r
+       modexFadeOff(4, gpal);\r
+#endif\r
+       VGAmodeX(0, 1, &gvar);\r
+#endif\r
+       IN_Shutdown();\r
+       MM_FreePtr(&bigbuffer, &gvar.mm);\r
+       CA_Shutdown(&gvar);\r
+       MM_Shutdown(&gvar.mm);\r
+       printf("\nProject 16 scroll.exe. This is just a test file!\n");\r
+       printf("version %s\n", VERSION);\r
+       printf("tx: %d  ", mv[0].tx);\r
+       printf("ty: %d\n", mv[0].ty);\r
+       printf("\n");\r
+       printf("player vars:\n");\r
+       printf("        x: %d", player[0].x); printf("  y: %d\n", player[0].y);\r
+       //if(player[0].hp==0) printf("%d wwww\n", player[0].y+8);\r
+       //else printf("\nplayer[0].y: %d\n", player[0].y);\r
+       printf("        tx: %d", player[0].tx); printf("        ty: %d\n", player[0].ty);\r
+       printf("        triggx: %d", player[0].triggerx); printf("      triggy: %d\n", player[0].triggery);\r
+       printf("        hp: %d", (player[0].hp));       printf("        q: %d", player[0].q);   printf("        player.info.dir: %d", player[0].info.dir);      printf("        player.d: %d ", player[0].d);\r
+               printf("        pdir=%d\n", player[0].pdir);\r
+       printf("        tile data value at player trigger position: %d\n\n", mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))]);\r
+//     printf("palette offset: %d\n", paloffset/3);\r
+//++++ printf("Total used: %zu\n", oldfreemem-GetFreeSize());\r
+//++++ printf("Total free: %zu\n", GetFreeSize());\r
+//not used now printf("temporary player sprite 0: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=45556867\n");\r
+//not used now printf("temporary player sprite 1: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=44606385\n");\r
+       printf("Virtual Screen: %dx", gvar.video.page[0].width);        printf("%d      ", gvar.video.page[0].height);\r
+       printf("Screen: %dx", gvar.video.page[0].sw);   printf("%d\n", gvar.video.page[0].sh);\r
+       printf("virtual tile resolution: %dx", gvar.video.page[0].tilesw);      printf("%d      ", gvar.video.page[0].tilesh);\r
+       printf("tile resolution: %dx", gvar.video.page[0].tw);  printf("%d\n", gvar.video.page[0].th);\r
+       printf("middle tile position: %dx", gvar.video.page[0].tilemidposscreenx);      printf("%d\n", gvar.video.page[0].tilemidposscreeny);\r
+       modexprintmeminfo(&gvar.video);\r
+       //printf("mv[%u].tx: %d", pan.pn, mv[pan.pn].tx); printf("      mv[%u].ty: %d   ", pan.pn, mv[pan.pn].ty);\r
+       printf("gvar.video.p=%u ", gvar.video.p); printf("gvar.video.r=%u ", gvar.video.r);\r
+       printf("pageflipflop=%u\n", pageflipflop);\r
+       //0000printf("\ngvar.video.tickclk=%f\n", gvar.video.tickclk);\r
+       //0000printf("gvar.video.clk=%f", gvar.video.clk);\r
+       printf("\n");\r
+       //printf("map.width=%d  map.height=%d   map.data[0]=%d\n", mv[0].map->width, mv[0].map->height, mv[0].map->data[0]);\r
+\r
+       printf("\n");\r
+       switch(detectcpu())\r
+       {\r
+               case 0: cpus = "8086/8088 or 186/88"; break;\r
+               case 1: cpus = "286"; break;\r
+               case 2: cpus = "386 or newer"; break;\r
+               default: cpus = "internal error"; break;\r
+       }\r
+       printf("detected CPU type: %s\n", cpus);\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       modexFadeOn(4, dpal);\r
+#endif\r
+#endif\r
+}\r
index a74e7711dc3b7afd02629d749879cabc7d35c110..00fc689f94c1be2db7d25c24bcad660cb87149b9 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You screen.heightould have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "src/bakapi.h"
-
-/*
- * BAKAPEE!
- */
-global_game_variables_t gvar;
-static bakapee_t bakapee;
-word key,d,xpos,ypos,xdir,ydir;
-sword vgamodex_mode = 1; // 320x240 default
-int ch=0x0;
-
-void
-main(int argc, char *argvar[])
-{
-       char *a;
-       int i;
-       word panq=1, pand=0;
-       boolean panswitch=0;
-
-       // allow changing default mode from command line
-       for (i=1;i < argc;) {
-               a = argvar[i++];
-
-               if (*a == '-') {
-                       do { a++; } while (*a == '-');
-
-                       if (!strcmp(a,"mx")) {
-                               // (based on src/lib/modex16.c)
-                               // 1 = 320x240
-                               // 2 = 160x120
-                               // 3 = 320x200
-                               // 4 = 192x144
-                               // 5 = 256x192
-                               vgamodex_mode = (sword)strtoul(argvar[i++],NULL,0);
-                       }
-                       else {
-                               fprintf(stderr,"Unknown switch %s\n",a);
-                               return;
-                       }
-               }
-               else {
-                       fprintf(stderr,"Unknown command arg %s\n",a);
-                       return;
-               }
-       }
-
-       // DOSLIB: check our environment
-       probe_dos();
-
-       // DOSLIB: what CPU are we using?
-       // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS.
-       //      So this code by itself shouldn't care too much what CPU it's running on. Except that other
-       //      parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for
-       //      the CPU to carry out tasks. --J.C.
-       cpu_probe();
-
-       // DOSLIB: check for VGA
-       if (!probe_vga()) {
-               printf("VGA probe failed\n");
-               return;
-       }
-       // hardware must be VGA or higher!
-       if (!(vga_state.vga_flags & VGA_IS_VGA)) {
-               printf("This program requires VGA or higher graphics hardware\n");
-               return;
-       }
-
-       // main variables values
-       d=4; // switch variable
-       key=2; // default screensaver number
-       xpos=TILEWHD;
-       ypos=TILEWHD;
-       xdir=1;
-       ydir=1;
-
-       VGAmodeX(vgamodex_mode, 1, &gvar); // TODO: Suggestion: Instead of magic numbers for the first param, might I suggest defining an enum or some #define constants that are easier to remember? --J.C.
-               // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in.
-               // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C.
-
-       bakapee.xx = rand()&0%gvar.video.page[0].width;
-       bakapee.yy = rand()&0%gvar.video.page[0].height;
-       bakapee.gq = 0;
-       bakapee.sx=0;
-       bakapee.sy=0;
-       bakapee.bakax=0;
-       bakapee.bakay=0;
-       bakapee.coor=0;
-       bakapee.tile=0;
-
-       /* setup camera and screen~ */
-       gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]);
-       textInit();
-
-       //modexPalUpdate(bmp.palette); //____
-       //modexDrawBmp(VGA, 0, 0, &bmp, 0); //____
-       //getch(); //____
-
-       modexShowPage(&gvar.video.page[0]);
-
-// screen savers
-#ifdef BOINK
-       while(d>0)      // on!
-       {
-               int c;
-               /* run screensaver routine until keyboard input */
-               while (key > 0) {
-                       if (kbhit()) {
-                               if(!panswitch)
-                               {
-                                       getch(); // eat keyboard input
-                                       break;
-                               }else c=getch();
-                       }
-
-                       if(!panswitch)  ding(&gvar.video.page[0], &bakapee, key);
-                       else                    ding(&gvar.video.page[0], &bakapee, 2);
-                       if(panswitch!=0)
-                       {
-                               //right movement
-                               if((c==0x4d && pand == 0) || pand == 2)
-                               {
-                                       if(pand == 0){ pand = 2; }
-                                       if(panq<=(TILEWH/(4)))
-                                       {
-                                               gvar.video.page[0].dx++;
-                                               modexShowPage(&gvar.video.page[0]);
-                                               panq++;
-                                       } else { panq = 1; pand = 0; }
-                               }
-                               //left movement
-                               if((c==0x4b && pand == 0) || pand == 4)
-                               {
-                                       if(pand == 0){ pand = 4; }
-                                       if(panq<=(TILEWH/(4)))
-                                       {
-                                               gvar.video.page[0].dx--;
-                                               modexShowPage(&gvar.video.page[0]);
-                                               panq++;
-                                       } else { panq = 1; pand = 0; }
-                               }
-                               //down movement
-                               if((c==0x50 && pand == 0) || pand == 3)
-                               {
-                                       if(pand == 0){ pand = 3; }
-                                       if(panq<=(TILEWH/(4)))
-                                       {
-                                               gvar.video.page[0].dy++;
-                                               modexShowPage(&gvar.video.page[0]);
-                                               panq++;
-                                       } else { panq = 1; pand = 0; }
-                               }
-                               //up movement
-                               if((c==0x48 && pand == 0) || pand == 1)
-                               {
-                                       if(pand == 0){ pand = 1; }
-                                       if(panq<=(TILEWH/(4)))
-                                       {
-                                               gvar.video.page[0].dy--;
-                                               modexShowPage(&gvar.video.page[0]);
-                                               panq++;
-                                       } else { panq = 1; pand = 0; }
-                               }
-                               if(c==0x71 || c==0xb1 || c=='p')
-                               {
-                                       //getch(); // eat keyboard input
-                                       panswitch=0;
-                                       break; // 'q' or 'ESC' or 'p'
-                               }
-                       }
-               }
-
-               {
-
-               // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in.
-               // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C.
-                       VGAmodeX(0, 0, &gvar);
-                       // user imput switch
-                       //fprintf(stderr, "xx=%d        yy=%d   tile=%d\n", bakapee.xx, bakapee.yy, bakapee.tile);
-                       //fprintf(stderr, "dx=%d        dy=%d   ", gvar.video.page[0].dx, gvar.video.page[0].dy);
-                       printf("Tiled mode is ");
-                       switch (bakapee.tile)
-                       {
-                               case 0:
-                                       printf("off.    ");
-                               break;
-                               case 1:
-                                       printf("on.     ");
-                               break;
-                       }
-                       //printf("\n");
-                       printf("Pan mode is ");
-                       switch (panswitch)
-                       {
-                               case 0:
-                                       printf("off.\n");
-                               break;
-                               case 1:
-                                       printf("on.\n");
-                               break;
-                       }
-                       printf("Enter 1, 2, 3, 4, 5, 6, 8, or 9 to run a screensaver, or enter 0 to quit.\n");
-pee:
-                       c = getch();
-                       switch (c) {
-                               case 27: /* Escape key */
-                               case '0':
-                                       d=0;
-                                       break;
-                               case 'p': // test pan
-                               switch (panswitch)
-                               {
-                                       case 0:
-                                               panswitch=1;
-                                       break;
-                                       case 1:
-                                               panswitch=0;
-                                       break;
-                               }
-                               goto pee;
-                               break;
-                               case 'b': // test tile change
-                                       switch (bakapee.tile)
-                                       {
-                                               case 0:
-                                                       bakapee.tile=1;
-                                               break;
-                                               case 1:
-                                                       bakapee.tile=0;
-                                               break;
-                                       }
-                                       key=0;
-                                       break;
-                               case '8':
-                                       c+=8;
-                               case '1':
-                               case '2':
-                               case '3':
-                               case '4':
-                               case '5':
-                               case '6':
-                               case '9':
-                                       key = c - '0';
-                                       VGAmodeX(vgamodex_mode, 0, &gvar);
-                                       gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]);
-               // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in.
-               // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C.
-                                       modexShowPage(&gvar.video.page[0]);
-                                       break;
-                               default:
-                                       key=0;
-                                       break;
-                       }
-               }
-       }
-#else // !defined(BOINK)
-// FIXME: Does not compile. Do you want to remove this?
-// TODO: This is a testing sextion for textrendering and panning for project 16 --sparky4
-       while(1)
-       { // conditions of screen saver
-//             while(!kbhit())
-//             {
-//                     ding(&gvar.video.page[0], &bakapee, key);
-//             }
-               //end of screen savers
-               //pdump(&gvar.video.page[0]);
-
-//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-48, "========================================");
-//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-40, "|    |Chikyuu:$line1");
-//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-32, "|    |$line2");
-//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-24, "|    |$line3");
-//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-16, "|    |$line4");
-//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-8,  "========================================");
-
-       ding(&gvar.video.page[0], &bakapee, key);
-       modexPanPage(&gvar.video.page[0], xpos, ypos);
-       c = getch();
-
-//     xpos+=xdir;
-//     ypos+=ydir;
-//     if( (xpos>(gvar.video.page[0].sw-gvar.video.page[0].width-1))  || (xpos<1)){xdir=-xdir;}
-//     if( (ypos>(gvar.video.page[0].sh-gvar.video.page[0].height-1)) || (ypos<1)){ydir=-ydir;}
-//     ch=getch();
-       if(ch==0x71)break; // 'q'
-       if(ch==0x1b)break; // 'ESC'
-       }
-       VGAmodeX(0, 1, &gvar);
-#endif // defined(BOINK)
-//     printf("page.width=%u   ", gvar.video.page[0].width); printf("page.height=%u\n", gvar.video.page[0].height);
-       printf("bakapi ver. 1.04.16.04\nis made by sparky4\81i\81\86\83Ö\81\85\81j feel free to use it ^^\nLicence: GPL v3\n");
-       printf("compiled on 2016/04/04\n");
-}
-//pee!
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You screen.heightould have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "src/bakapi.h"\r
+\r
+/*\r
+ * BAKAPEE!\r
+ */\r
+global_game_variables_t gvar;\r
+static bakapee_t bakapee;\r
+word key,d,xpos,ypos,xdir,ydir;\r
+sword vgamodex_mode = 1; // 320x240 default\r
+int ch=0x0;\r
+\r
+void\r
+main(int argc, char *argvar[])\r
+{\r
+       char *a;\r
+       int i;\r
+       word panq=1, pand=0;\r
+       boolean panswitch=0;\r
+\r
+       // allow changing default mode from command line\r
+       for (i=1;i < argc;) {\r
+               a = argvar[i++];\r
+\r
+               if (*a == '-') {\r
+                       do { a++; } while (*a == '-');\r
+\r
+                       if (!strcmp(a,"mx")) {\r
+                               // (based on src/lib/modex16.c)\r
+                               // 1 = 320x240\r
+                               // 2 = 160x120\r
+                               // 3 = 320x200\r
+                               // 4 = 192x144\r
+                               // 5 = 256x192\r
+                               vgamodex_mode = (sword)strtoul(argvar[i++],NULL,0);\r
+                       }\r
+                       else {\r
+                               fprintf(stderr,"Unknown switch %s\n",a);\r
+                               return;\r
+                       }\r
+               }\r
+               else {\r
+                       fprintf(stderr,"Unknown command arg %s\n",a);\r
+                       return;\r
+               }\r
+       }\r
+\r
+       // DOSLIB: check our environment\r
+       probe_dos();\r
+\r
+       // DOSLIB: what CPU are we using?\r
+       // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS.\r
+       //      So this code by itself shouldn't care too much what CPU it's running on. Except that other\r
+       //      parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for\r
+       //      the CPU to carry out tasks. --J.C.\r
+       cpu_probe();\r
+\r
+       // DOSLIB: check for VGA\r
+       if (!probe_vga()) {\r
+               printf("VGA probe failed\n");\r
+               return;\r
+       }\r
+       // hardware must be VGA or higher!\r
+       if (!(vga_state.vga_flags & VGA_IS_VGA)) {\r
+               printf("This program requires VGA or higher graphics hardware\n");\r
+               return;\r
+       }\r
+\r
+       // main variables values\r
+       d=4; // switch variable\r
+       key=2; // default screensaver number\r
+       xpos=TILEWHD;\r
+       ypos=TILEWHD;\r
+       xdir=1;\r
+       ydir=1;\r
+\r
+       VGAmodeX(vgamodex_mode, 1, &gvar); // TODO: Suggestion: Instead of magic numbers for the first param, might I suggest defining an enum or some #define constants that are easier to remember? --J.C.\r
+               // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in.\r
+               // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C.\r
+\r
+       bakapee.xx = rand()&0%gvar.video.page[0].width;\r
+       bakapee.yy = rand()&0%gvar.video.page[0].height;\r
+       bakapee.gq = 0;\r
+       bakapee.sx=0;\r
+       bakapee.sy=0;\r
+       bakapee.bakax=0;\r
+       bakapee.bakay=0;\r
+       bakapee.coor=0;\r
+       bakapee.tile=0;\r
+\r
+       /* setup camera and screen~ */\r
+       gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]);\r
+       textInit();\r
+\r
+       //modexPalUpdate(bmp.palette); //____\r
+       //modexDrawBmp(VGA, 0, 0, &bmp, 0); //____\r
+       //getch(); //____\r
+\r
+       modexShowPage(&gvar.video.page[0]);\r
+\r
+// screen savers\r
+#ifdef BOINK\r
+       while(d>0)      // on!\r
+       {\r
+               int c;\r
+               /* run screensaver routine until keyboard input */\r
+               while (key > 0) {\r
+                       if (kbhit()) {\r
+                               if(!panswitch)\r
+                               {\r
+                                       getch(); // eat keyboard input\r
+                                       break;\r
+                               }else c=getch();\r
+                       }\r
+\r
+                       if(!panswitch)  ding(&gvar.video.page[0], &bakapee, key);\r
+                       else                    ding(&gvar.video.page[0], &bakapee, 2);\r
+                       if(panswitch!=0)\r
+                       {\r
+                               //right movement\r
+                               if((c==0x4d && pand == 0) || pand == 2)\r
+                               {\r
+                                       if(pand == 0){ pand = 2; }\r
+                                       if(panq<=(TILEWH/(4)))\r
+                                       {\r
+                                               gvar.video.page[0].dx++;\r
+                                               modexShowPage(&gvar.video.page[0]);\r
+                                               panq++;\r
+                                       } else { panq = 1; pand = 0; }\r
+                               }\r
+                               //left movement\r
+                               if((c==0x4b && pand == 0) || pand == 4)\r
+                               {\r
+                                       if(pand == 0){ pand = 4; }\r
+                                       if(panq<=(TILEWH/(4)))\r
+                                       {\r
+                                               gvar.video.page[0].dx--;\r
+                                               modexShowPage(&gvar.video.page[0]);\r
+                                               panq++;\r
+                                       } else { panq = 1; pand = 0; }\r
+                               }\r
+                               //down movement\r
+                               if((c==0x50 && pand == 0) || pand == 3)\r
+                               {\r
+                                       if(pand == 0){ pand = 3; }\r
+                                       if(panq<=(TILEWH/(4)))\r
+                                       {\r
+                                               gvar.video.page[0].dy++;\r
+                                               modexShowPage(&gvar.video.page[0]);\r
+                                               panq++;\r
+                                       } else { panq = 1; pand = 0; }\r
+                               }\r
+                               //up movement\r
+                               if((c==0x48 && pand == 0) || pand == 1)\r
+                               {\r
+                                       if(pand == 0){ pand = 1; }\r
+                                       if(panq<=(TILEWH/(4)))\r
+                                       {\r
+                                               gvar.video.page[0].dy--;\r
+                                               modexShowPage(&gvar.video.page[0]);\r
+                                               panq++;\r
+                                       } else { panq = 1; pand = 0; }\r
+                               }\r
+                               if(c==0x71 || c==0xb1 || c=='p')\r
+                               {\r
+                                       //getch(); // eat keyboard input\r
+                                       panswitch=0;\r
+                                       break; // 'q' or 'ESC' or 'p'\r
+                               }\r
+                       }\r
+               }\r
+\r
+               {\r
+\r
+               // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in.\r
+               // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C.\r
+                       VGAmodeX(0, 0, &gvar);\r
+                       // user imput switch\r
+                       //fprintf(stderr, "xx=%d        yy=%d   tile=%d\n", bakapee.xx, bakapee.yy, bakapee.tile);\r
+                       //fprintf(stderr, "dx=%d        dy=%d   ", gvar.video.page[0].dx, gvar.video.page[0].dy);\r
+                       printf("Tiled mode is ");\r
+                       switch (bakapee.tile)\r
+                       {\r
+                               case 0:\r
+                                       printf("off.    ");\r
+                               break;\r
+                               case 1:\r
+                                       printf("on.     ");\r
+                               break;\r
+                       }\r
+                       //printf("\n");\r
+                       printf("Pan mode is ");\r
+                       switch (panswitch)\r
+                       {\r
+                               case 0:\r
+                                       printf("off.\n");\r
+                               break;\r
+                               case 1:\r
+                                       printf("on.\n");\r
+                               break;\r
+                       }\r
+                       printf("Enter 1, 2, 3, 4, 5, 6, 8, or 9 to run a screensaver, or enter 0 to quit.\n");\r
+pee:\r
+                       c = getch();\r
+                       switch (c) {\r
+                               case 27: /* Escape key */\r
+                               case '0':\r
+                                       d=0;\r
+                                       break;\r
+                               case 'p': // test pan\r
+                               switch (panswitch)\r
+                               {\r
+                                       case 0:\r
+                                               panswitch=1;\r
+                                       break;\r
+                                       case 1:\r
+                                               panswitch=0;\r
+                                       break;\r
+                               }\r
+                               goto pee;\r
+                               break;\r
+                               case 'b': // test tile change\r
+                                       switch (bakapee.tile)\r
+                                       {\r
+                                               case 0:\r
+                                                       bakapee.tile=1;\r
+                                               break;\r
+                                               case 1:\r
+                                                       bakapee.tile=0;\r
+                                               break;\r
+                                       }\r
+                                       key=0;\r
+                                       break;\r
+                               case '8':\r
+                                       c+=8;\r
+                               case '1':\r
+                               case '2':\r
+                               case '3':\r
+                               case '4':\r
+                               case '5':\r
+                               case '6':\r
+                               case '9':\r
+                                       key = c - '0';\r
+                                       VGAmodeX(vgamodex_mode, 0, &gvar);\r
+                                       gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]);\r
+               // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in.\r
+               // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C.\r
+                                       modexShowPage(&gvar.video.page[0]);\r
+                                       break;\r
+                               default:\r
+                                       key=0;\r
+                                       break;\r
+                       }\r
+               }\r
+       }\r
+#else // !defined(BOINK)\r
+// FIXME: Does not compile. Do you want to remove this?\r
+// INFO: This is a testing section for textrendering and panning for project 16 --sparky4\r
+       while(1)\r
+       { // conditions of screen saver\r
+//             while(!kbhit())\r
+//             {\r
+//                     ding(&gvar.video.page[0], &bakapee, key);\r
+//             }\r
+               //end of screen savers\r
+               //pdump(&gvar.video.page[0]);\r
+\r
+//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-48, "========================================");\r
+//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-40, "|    |Chikyuu:$line1");\r
+//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-32, "|    |$line2");\r
+//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-24, "|    |$line3");\r
+//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-16, "|    |$line4");\r
+//             mxOutText(xpos+1, ypos+gvar.video.page[0].height-8,  "========================================");\r
+\r
+       ding(&gvar.video.page[0], &bakapee, key);\r
+       modexPanPage(&gvar.video.page[0], xpos, ypos);\r
+       c = getch();\r
+\r
+//     xpos+=xdir;\r
+//     ypos+=ydir;\r
+//     if( (xpos>(gvar.video.page[0].sw-gvar.video.page[0].width-1))  || (xpos<1)){xdir=-xdir;}\r
+//     if( (ypos>(gvar.video.page[0].sh-gvar.video.page[0].height-1)) || (ypos<1)){ydir=-ydir;}\r
+//     ch=getch();\r
+       if(ch==0x71)break; // 'q'\r
+       if(ch==0x1b)break; // 'ESC'\r
+       }\r
+       VGAmodeX(0, 1, &gvar);\r
+#endif // defined(BOINK)\r
+//     printf("page.width=%u   ", gvar.video.page[0].width); printf("page.height=%u\n", gvar.video.page[0].height);\r
+       printf("bakapi ver. 1.04.16.04\nis made by sparky4\81i\81\86\83Ö\81\85\81j feel free to use it ^^\nLicence: GPL v3\n");\r
+       printf("compiled on 2016/04/04\n");\r
+}\r
+//pee!\r
index 1270fab732222efb06a5dc4b4c4a5215e4374048..7c1fb1ab8531176d8fa27149e49d9352ec765bbe 100755 (executable)
@@ -1,31 +1,31 @@
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __BAKAPI_H_
-#define __BAKAPI_H_
-
-#include "src/lib/bakapee.h"
-
-//project 16 testing define switch for veiwing the contents of the video memory --sparky4
-#define BOINK // what does this mean? --J.C.
-
-#endif /*__BAKAPI_H_*/
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#ifndef __BAKAPI_H_\r
+#define __BAKAPI_H_\r
+\r
+#include "src/lib/bakapee.h"\r
+\r
+//project 16 testing define switch for veiwing the contents of the video memory --sparky4\r
+#define BOINK // what does this mean? --J.C.\r
+\r
+#endif /*__BAKAPI_H_*/\r
index eefab9ea8cf7337f1a8740d6b0ba38818e92614e..e8bfe1f549254a0d9c32df7287073c8b8e6b001d 100755 (executable)
@@ -8,8 +8,8 @@
 \r
         minor mods by Alex Russell to simplify\r
 \r
-        Must use memory model with FAR code
-
+        Must use memory model with FAR code\r
+\r
                Open Watcom patch by sparky4~\r
 \r
  */\r
 #include <stdio.h>\r
 #include <stdlib.h>\r
 #include <mem.h>\r
-#include <conio.h>
+#include <conio.h>\r
+\r
+#include "src/lib/exmm/memory.h"\r
+#include "src/lib/types.h"\r
 \r
-#include "src/lib/exmm/memory.h"
-#include "src/lib/types.h"
-
 #define PEMMDATAPAGENUM        4\r
 \r
 void TransformData(char *pEmmData, unsigned int len)\r
@@ -37,30 +37,30 @@ void TransformData(char *pEmmData, unsigned int len)
 \r
 int main(int argc, char *argv[])\r
 {\r
-       byte *pEmmData;
-       int hEData;
-       unsigned long advi;
-       unsigned long i=0;
-       char huge *p =(char huge *)(GetEMMSeg0()*0x10000);
+       byte *pEmmData;\r
+       int hEData;\r
+       unsigned long advi;\r
+       unsigned long i=0;\r
+       char huge *p =(char huge *)(GetEMMSeg0()*0x10000);\r
 \r
        if(OpenEMM() != SUCCESS)\r
        {               // make sure we got EMM\r
                printf("EMM unavailable.\n");\r
                exit(1);\r
        }\r
-       else
+       else\r
        {\r
-               printf("Emm %x available\n", EMVer());
-               printf("EMS pages available are %lu\n", EMMCoreLeft());
-               //printf("EMM Hardware Information %lu\n", EMInfo());
+               printf("Emm %x available\n", EMVer());\r
+               printf("EMS pages available are %lu\n", EMMCoreLeft());\r
+               //printf("EMM Hardware Information %lu\n", EMInfo());\r
        }\r
-
-       printf("b4 EMS          pEmmData=%p\n", pEmmData);
-       //printf("b4 EMS        *pEmmData=%s\n", *pEmmData);
-       advi=EMMCoreLeft()*EMMPAGESIZE;
-       printf("advi=%lu\n", advi);
-
-       pEmmData = (byte *)EMMalloc(&hEData, EMMCoreLeft());  // get 6 * 16K bytes - 96K
+\r
+       printf("b4 EMS          pEmmData=%p\n", pEmmData);\r
+       //printf("b4 EMS        *pEmmData=%s\n", *pEmmData);\r
+       advi=EMMCoreLeft()*EMMPAGESIZE;\r
+       printf("advi=%lu\n", advi);\r
+\r
+       pEmmData = (byte *)EMMalloc(&hEData, EMMCoreLeft());  // get 6 * 16K bytes - 96K\r
        if(pEmmData == NULL/* ||  pEmmData0 == NULL*/)\r
        {\r
                printf("Not enough EMM or out of handles.\n");\r
@@ -68,73 +68,73 @@ int main(int argc, char *argv[])
        }\r
        else\r
                printf("EMM allocate OK\n");\r
-
-       printf("EMS pages available are %lu\n", EMMCoreLeft());
-
-
-
+\r
+       printf("EMS pages available are %lu\n", EMMCoreLeft());\r
+\r
+\r
+\r
        printf("Map 1st 4 pages\n");\r
        MapEMM(hEData, 0, PEMMDATAPAGENUM);   // load 1st 4 pages into page frame: 0-3\r
-       //memset(pEmmData, 0x0e, 64000u);
-//0000 printf("(advi*EMMPAGESIZE)=%lu\n", advi);
-       memset(pEmmData, atoi(argv[1]), 0xffff);//sizeof(atoi(argv[1])));//((EMMCoreLeft())*EMMPAGESIZE));
-//qqqq memset(pEmmData+0x10000, atoi(argv[1]), 0xffff);//sizeof(atoi(argv[1])));//((EMMCoreLeft())*EMMPAGESIZE));
-//---- UnmapEMM(hEData, 0, 4);          // not absolutely necessary
-       printf("%p= %c %c %c %c %c %c %c %c\n", pEmmData,
-*pEmmData, *(pEmmData+1), *(pEmmData+2), *(pEmmData+3), *(pEmmData+4), *(pEmmData+5), *(pEmmData+6), *(pEmmData+7));
+       //memset(pEmmData, 0x0e, 64000u);\r
+//0000 printf("(advi*EMMPAGESIZE)=%lu\n", advi);\r
+       memset(pEmmData, atoi(argv[1]), 0xffff);//sizeof(atoi(argv[1])));//((EMMCoreLeft())*EMMPAGESIZE));\r
+//qqqq memset(pEmmData+0x10000, atoi(argv[1]), 0xffff);//sizeof(atoi(argv[1])));//((EMMCoreLeft())*EMMPAGESIZE));\r
+//---- UnmapEMM(hEData, 0, 4);          // not absolutely necessary\r
+       printf("%p= %c %c %c %c %c %c %c %c\n", pEmmData,\r
+*pEmmData, *(pEmmData+1), *(pEmmData+2), *(pEmmData+3), *(pEmmData+4), *(pEmmData+5), *(pEmmData+6), *(pEmmData+7));\r
 \r
        /*printf("Map next 2 pages\n");\r
        MapEMM(hEData, 4, 2);            // map last 2 pages: 4-5\r
-       memset(pEmmData, 0x04, 32768u);
-//     memset(pEmmData, atoi(argv[0]), 32768u);
-       printf("*pEmmData=%c\n", *pEmmData);
-       printf(" pEmmData=%p\n", pEmmData);*/
+       memset(pEmmData, 0x04, 32768u);\r
+//     memset(pEmmData, atoi(argv[0]), 32768u);\r
+       printf("*pEmmData=%c\n", *pEmmData);\r
+       printf(" pEmmData=%p\n", pEmmData);*/\r
 \r
    /*MapEMM(hEData, 0, 4);\r
    // do some stuff with the first 64K of file data.\r
    printf("Transform data\n");\r
-   TransformData(pEmmData, 64000UL);
+   TransformData(pEmmData, 64000UL);\r
        printf("*pEmmData=%lu\n", *pEmmData);\r
    MapEMM(hEData, 4, 2);  // only unmaps 1st two pages of prior 64k mapping\r
    // do stuff with remaining 32K of data\r
-   TransformData(pEmmData, 32768UL);
-       printf("*pEmmData=%lu\n", *pEmmData);*/
-       if(atoi(argv[2]))
-       {
-               while(p<(char huge *)((GetEMMSeg0()*0x10000)+0xffff) && !kbhit())
-               {
-                       if((i%16)==0) printf("%p= %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", p,
-*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7),
-*(p+8), *(p+9), *(p+10), *(p+11), *(p+12), *(p+13), *(p+14), *(p+15));
-       //              (*p)++;
-                       i++;
-                       p++;
-               }
-       }
-       /*if(atoi(argv[3]))
-               p =(char huge *)(GetEMMSeg0()*0x20000);
-               while(p<(char huge *)((GetEMMSeg0()*0x20000)+0xffff) && !kbhit())
-               {
-                       if((i%16)==0) printf("%p= %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", p,
-*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7),
-*(p+8), *(p+9), *(p+10), *(p+11), *(p+12), *(p+13), *(p+14), *(p+15));
-       //              (*p)++;
-                       i++;
-                       p++;
-               }
-               //free(p);
-       }*/
-       if(!atoi(argv[3]))
+   TransformData(pEmmData, 32768UL);\r
+       printf("*pEmmData=%lu\n", *pEmmData);*/\r
+       if(atoi(argv[2]))\r
        {\r
-               UnmapEMM(hEData, 0, PEMMDATAPAGENUM);  // should unmap before freeing
+               while(p<(char huge *)((GetEMMSeg0()*0x10000)+0xffff) && !kbhit())\r
+               {\r
+                       if((i%16)==0) printf("%p= %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", p,\r
+*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7),\r
+*(p+8), *(p+9), *(p+10), *(p+11), *(p+12), *(p+13), *(p+14), *(p+15));\r
+       //              (*p)++;\r
+                       i++;\r
+                       p++;\r
+               }\r
+       }\r
+       /*if(atoi(argv[3]))\r
+               p =(char huge *)(GetEMMSeg0()*0x20000);\r
+               while(p<(char huge *)((GetEMMSeg0()*0x20000)+0xffff) && !kbhit())\r
+               {\r
+                       if((i%16)==0) printf("%p= %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", p,\r
+*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7),\r
+*(p+8), *(p+9), *(p+10), *(p+11), *(p+12), *(p+13), *(p+14), *(p+15));\r
+       //              (*p)++;\r
+                       i++;\r
+                       p++;\r
+               }\r
+               //free(p);\r
+       }*/\r
+       if(!atoi(argv[3]))\r
+       {\r
+               UnmapEMM(hEData, 0, PEMMDATAPAGENUM);  // should unmap before freeing\r
                //printf("after EMS     *pEmmData=%c\n", *pEmmData);\r
                printf("Close emm\n");\r
                EMMFree(hEData);     // finished with the file data\r
-               CloseEMM();
-       }
-       printf("after EMS       pEmmData=%p\n", pEmmData);
-       printf("EMS pages available are %lu\n", EMMCoreLeft());
-       printf("GetEMMSeg0=%p\n", GetEMMSeg0()*0x10000);
-       //printf("EMMPAGESIZE=%d\n", EMMPAGESIZE);
-       return 0;
+               CloseEMM();\r
+       }\r
+       printf("after EMS       pEmmData=%p\n", pEmmData);\r
+       printf("EMS pages available are %lu\n", EMMCoreLeft());\r
+       printf("GetEMMSeg0=%p\n", GetEMMSeg0()*0x10000);\r
+       //printf("EMMPAGESIZE=%d\n", EMMPAGESIZE);\r
+       return 0;\r
 }\r
index b07f7c66d86c976cbcf688578e7a531e64118e5d..4506986331adef8a881472fc6c6dfaec4a30bb74 100755 (executable)
@@ -1,58 +1,58 @@
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include<stdio.h>
-#include <conio.h>
-//#include <limits.h>
-
-#include "src/lib/exmm/memory.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned long i=0;
-       char near w;
-       char huge *p =(char huge *)(GetEMMSeg0()*0x10000);//0xD0000000;
-       //char far *q =(char far *)0x53332225;
-       printf("1p=%p   %ul\n", p, GetEMMSeg0());
-       //while(!kbhit()){              printf("%p\n", ((GetEMMSeg0()*0x10000)+0x0fffffff));    }
-       //while(!kbhit()){              printf("%p\n", ((GetEMMSeg0()*0x10000)+0xffff));        }
-       if(argv[1])     {               printf("switch on!\n");         while(!kbhit()){}       }
-       while(p<=(char huge *)((GetEMMSeg0()*0x10000)+0xffff)/*i<262144UL*/ && !kbhit())
-       {
-               if(argv[1]!=NULL) (*p) = i; else
-               //else printf("%p=      %x%     %ul\n", p, *p, i);
-               if((i%8)==0) printf("%p= %c %c %c %c %c %c %c %c\n", p,
-*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7));
-//             (*p)++;
-//             printf("                                %p\n", ((GetEMMSeg0()*0x10000)+0x0fffffff));
-               i++;
-               p++;
-       }
-       w=104;
-       //printf("*q=%d\n",*q);
-       //printf(" q=%p\n", q);
-       printf(" p=%p\n", p);
-       printf(" w=%d\n", w);
-       printf(" w=%p\n", w);
-       printf("GetEMMSeg0()=%p\n", GetEMMSeg0()*0x10000);
-       return 0;
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include<stdio.h>\r
+#include <conio.h>\r
+//#include <limits.h>\r
+\r
+#include "src/lib/exmm/memory.h"\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+       unsigned long i=0;\r
+       char near w;\r
+       char huge *p =(char huge *)(GetEMMSeg0()*0x10000);//0xD0000000;\r
+       //char far *q =(char far *)0x53332225;\r
+       printf("1p=%p   %ul\n", p, GetEMMSeg0());\r
+       //while(!kbhit()){              printf("%p\n", ((GetEMMSeg0()*0x10000)+0x0fffffff));    }\r
+       //while(!kbhit()){              printf("%p\n", ((GetEMMSeg0()*0x10000)+0xffff));        }\r
+       if(argv[1])     {               printf("switch on!\n");         while(!kbhit()){}       }\r
+       while(p<=(char huge *)((GetEMMSeg0()*0x10000)+0xffff)/*i<262144UL*/ && !kbhit())\r
+       {\r
+               if(argv[1]!=NULL) (*p) = i; else\r
+               //else printf("%p=      %x%     %ul\n", p, *p, i);\r
+               if((i%8)==0) printf("%p= %c %c %c %c %c %c %c %c\n", p,\r
+*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7));\r
+//             (*p)++;\r
+//             printf("                                %p\n", ((GetEMMSeg0()*0x10000)+0x0fffffff));\r
+               i++;\r
+               p++;\r
+       }\r
+       w=104;\r
+       //printf("*q=%d\n",*q);\r
+       //printf(" q=%p\n", q);\r
+       printf(" p=%p\n", p);\r
+       printf(" w=%d\n", w);\r
+       printf(" w=%p\n", w);\r
+       printf("GetEMMSeg0()=%p\n", GetEMMSeg0()*0x10000);\r
+       return 0;\r
+}\r
index f9c6500d20a55b9cd1797174a0a971e1c7f07fe3..8c570b2e1fe143f4102855d85c737325340efee6 100755 (executable)
@@ -1,7 +1,7 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "src\lib\ems.c"
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "src\lib\ems.c"\r
      /*\r
      Test function for the EMM routines\r
      */\r
@@ -55,4 +55,4 @@
           }\r
      \r
           emmclose(emmhandle);\r
-     }
+     }\r
index 02fafeb6aa1b63db68c9d010b2154a99d75b0afc..f68d148e99bb4e1e2bff099a8cf7d50a796f985d 100755 (executable)
@@ -23,6 +23,8 @@
        exmm test\r
 */\r
 #include "src/lib/16_head.h"\r
+#include "src/lib/16_tail.h"\r
+#include "src/lib/16_pm.h"\r
 #include "src/lib/16_ca.h"\r
 #include "src/lib/16_mm.h"\r
 #include "src/lib/16_hc.h"\r
@@ -60,12 +62,13 @@ void segatesuto()
 //     getch();\r
 }\r
 #endif\r
+//static global_game_variables_t gvar;\r
 \r
 void\r
 main(int argc, char *argv[])\r
 {\r
        byte w=1;\r
-       global_game_variables_t gvar;\r
+       static global_game_variables_t gvar;\r
 #ifdef __WATCOMC__\r
        __segment sega;\r
 #endif\r
@@ -84,6 +87,7 @@ main(int argc, char *argv[])
        //file name //\r
 \r
        gvar.mm.mmstarted=0;\r
+       dbg_debugpm=1;  //debug pm\r
 \r
        //PRINTBB\r
        if(argv[1]){ bakapee1 = argv[1];\r
@@ -93,13 +97,21 @@ main(int argc, char *argv[])
                bakapee1 = "data/koishi~.pcx";\r
                bakapee2 = "data/test.map";\r
        }\r
-//     printf("main()=%Fp      start MM\n", *argv[0]);\r
-       MM_Startup(&gvar.mm, &gvar.mmi);\r
-       //PM_Startup();\r
-       //PM_UnlockMainMem();\r
+       //printf("main()=%Fp    start MM\n", *argv[0]);\r
+       MM_Startup(&gvar);\r
+       //printf("ok\n");\r
+//#ifdef __WATCOMC__\r
+       if(dbg_debugpm>0)\r
+       {\r
+               PM_Startup(&gvar);\r
+               //printf("pmstarted ok\n");\r
+               //PM_CheckMainMem(&gvar);\r
+               PM_UnlockMainMem(&gvar);\r
+       }\r
+//#endif\r
        CA_Startup(&gvar);\r
 //     printf("                done!\n");\r
-       PRINTBB;\r
+       //0000PRINTBB;\r
 //     printf("press any key to continue!\n");\r
 //     getch();\r
 #ifdef FILEREAD\r
@@ -129,11 +141,8 @@ for(w=0;w<2;w++)
        //printf("dark purple = purgable\n");\r
        //printf("medium blue = non purgable\n");\r
        //printf("red = locked\n");\r
-       printf("press any key to continue!\n");\r
-       getch();\r
-       MM_ShowMemory(&gvar, &gvar.mm);\r
-       MM_DumpData(&gvar.mm);\r
-       MM_Report(&gvar);\r
+//     printf("press any key to continue!\n");\r
+//     DebugMemory_(&gvar, 1);\r
        if(baka) printf("\nyay!\n");\r
        else printf("\npoo!\n");\r
        printf("press any key to continue!\n");\r
@@ -141,10 +150,18 @@ for(w=0;w<2;w++)
 #ifdef FILEREAD\r
 }\r
 #endif\r
-       MM_FreePtr(&bigbuffer, &gvar.mm);\r
-       //PM_Shutdown();\r
+       DebugMemory_(&gvar, 1);\r
+       MM_DumpData(&gvar);\r
+       MM_Report_(&gvar);\r
+       //printf("bakapee1=%s\n", bakapee1);\r
+       //printf("bakapee2=%s\n", bakapee2);\r
+       MM_FreePtr(&bigbuffer, &gvar);\r
+//#ifdef __WATCOMC__\r
+       if(dbg_debugpm>0)\r
+               PM_Shutdown(&gvar);\r
+//#endif\r
        CA_Shutdown(&gvar);\r
-       MM_Shutdown(&gvar.mm);\r
+       MM_Shutdown(&gvar);\r
        free(bakapee1); free(bakapee2);\r
        printf("========================================\n");\r
        printf("near=   %Fp ", gvar.mm.nearheap);\r
@@ -160,12 +177,12 @@ for(w=0;w<2;w++)
        printf("&bigb=%Fp ", &bigbuffer);\r
        //printf("&bigb=%04x", &bigbuffer);\r
        printf("\n");\r
-#endif\r
        printf("========================================\n");\r
+#endif\r
 #ifdef __WATCOMC__\r
 //this is far  printf("Total free:                     %lu\n", (dword)(GetFreeSize()));\r
-       printf("Total near free:                %lu\n", (dword)(GetNearFreeSize()));\r
-       printf("Total far free:                 %lu\n", (dword)(GetFarFreeSize()));\r
+       printf("Total near free:                %lub\n", (dword)(GetNearFreeSize()));\r
+       printf("Total far free:                 %lub\n", (dword)(GetFarFreeSize()));\r
        heapdump(&gvar);\r
        segatesuto();\r
 #endif\r
index 62e2d8177b55a9fd0173487079b9f20bfc610eaa..be6ac4a2a725284c1f958afa1ada71b7fd4b86e5 100755 (executable)
@@ -30,8 +30,8 @@ main(int argc, char *argv[])
        global_game_variables_t gvar;\r
        player_t player[MaxPlayers];\r
        //extern struct inconfig inpu;\r
-       testkeyin=0;\r
-       testcontrolnoisy=1;\r
+       dbg_testkeyin=0;\r
+       dbg_testcontrolnoisy=1;\r
        IN_Startup();\r
        IN_Default(0,&player,ctrl_Joystick1);\r
        IN_SetControlType(0,&player,ctrl_Joystick1);\r
@@ -105,6 +105,6 @@ main(int argc, char *argv[])
        //printf("%u\n", in.Keyboard[sc_Escape]);\r
        printf("inputest.exe ");\r
        printf("version %s\n", VERSION);\r
-       printf("testkeyin=%u\n", testkeyin);\r
-       printf("testcontrolnoisy=%u\n", testcontrolnoisy);\r
+       printf("testkeyin=%u\n", dbg_testkeyin);\r
+       printf("testcontrolnoisy=%u\n", dbg_testcontrolnoisy);\r
 }\r
index 27e2d7ee366c94c49a3e3187fbded08af6625ae6..74fb0f676feae633d3e3eda60fd079cb7f5cde83 100755 (executable)
@@ -226,7 +226,7 @@ boolean CA_FarRead(int handle, byte huge *dest, dword length, global_game_variab
        boolean flag;\r
        //dword fat=0;\r
        //word segm=0;\r
-       if(gvar->mm.EMSVer<0x40)\r
+       if(gvar->pm.emm.EMSVer<0x40)\r
        if(length>0xfffflu)\r
        {\r
                printf("File is a fat bakapee\n");\r
@@ -298,7 +298,7 @@ boolean CA_FarWrite(int handle, byte huge *source, dword length, global_game_var
        boolean flag;\r
        //dword fat=0;\r
        //word segm=0;\r
-       if(gvar->mm.EMSVer<0x40)\r
+       if(gvar->pm.emm.EMSVer<0x40)\r
        if(length>0xfffflu)\r
        {\r
                printf("File is a fat bakapee\n");\r
@@ -438,7 +438,7 @@ boolean CA_LoadFile(char *filename, memptr *ptr, global_game_variables_t *gvar)
                return false;\r
 \r
        size = filelength(handle);\r
-       MM_GetPtr(ptr,size, &(gvar->mm), &(gvar->mmi)); //TODO: gvar parameters\r
+       MM_GetPtr(ptr,size, gvar);\r
        if(!CA_FarRead(handle,*ptr,size, gvar))\r
        {\r
                close(handle);\r
@@ -902,7 +902,7 @@ void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,
 //\r
 // NOTE: A repeat count that produces 0xfff0 bytes can blow this!\r
 //\r
-       __asm{\r
+       __asm {\r
                mov     bx,rlewtag\r
                mov     si,sourceoff\r
                mov     di,destoff\r
index 2215c42002c2acaa5ac9de10655db74ac1efa3a7..7766a1d443592a49cc64c032d357fa02e1a6584f 100755 (executable)
@@ -1,76 +1,76 @@
-
-#include "src/16.h"
-
-// TODO: Could we also provide a build mode to emit debug to the "Bochs E9 hack?"
-#ifdef DEBUGSERIAL
-# include <stdarg.h>
-# include <stdlib.h>
-# include <stdio.h>
-
-unsigned char _DEBUG_INITed = 0;
-struct info_8250 *_DEBUG_uart = NULL;
-
-int _DEBUG_INIT() {
-       if (!_DEBUG_INITed) {
-               unsigned int i;
-               uint16_t port;
-
-               if (!init_8250()) return 0;
-
-               // what does the BIOS say the serial ports are?
-               probe_8250_bios_ports();
-               for (i=0;i < bios_8250_ports;i++) {
-                       port = get_8250_bios_port(i);
-                       if (port == 0) continue;
-                       probe_8250(port);
-               }
-
-               // what about the standard serial ports?
-               for (i=0;i < (sizeof(standard_8250_ports)/sizeof(standard_8250_ports[0]));i++) {
-                       port = standard_8250_ports[i];
-                       if (port == 0) continue;
-                       probe_8250(port);
-               }
-
-               // pick the first port, which is probably COM1
-               if (base_8250_ports == 0) return 0; // FIXME: You know "base_8250_ports" is probably a bad variable name for the max entries in info_8250_port[]
-               _DEBUG_uart = &info_8250_port[0];
-               _DEBUG_INITed = 1;
-
-               // init the COM port.
-               // in DOSBox-X, the "log" mode will receive our text and print it into the log file
-               // on real hardware, our text will likely go over a null modem cable to another PC running a serial terminal program like PuTTY or minicom.
-               // if nothing is connected, then the bytes go off into the ether to get lost and life goes on.
-               uart_8250_enable_interrupt(_DEBUG_uart,0);      // disable interrupts
-               uart_8250_set_FIFO(_DEBUG_uart,0x07);           // enable FIFO (why not?), also clear xmit/recv FIFO buffers, set threshhold to 1 byte
-               uart_8250_set_MCR(_DEBUG_uart,3);               // RTS and DTS on
-               uart_8250_set_line_control(_DEBUG_uart,UART_8250_LCR_8BIT | UART_8250_LCR_PARITY); // 8 bit 1 stop bit odd parity
-               uart_8250_set_baudrate(_DEBUG_uart,uart_8250_baud_to_divisor(_DEBUG_uart,9600)); // 9600 baud
-       }
-
-       return _DEBUG_INITed;
-}
-
-void _DEBUG(const char *msg) {
-       if (_DEBUG_uart != NULL) {
-               char c;
-
-               while ((c=(*msg++)) != 0/*NUL*/) {
-                       while (!uart_8250_can_write(_DEBUG_uart)); // wait for the UART to indicate readiness for our output
-                       uart_8250_write(_DEBUG_uart,(uint8_t)c); // then write it
-               }
-       }
-}
-
-static char _DEBUGF_TMP[256];
-
-void _DEBUGF(const char *fmt,...) {
-       va_list va;
-
-       va_start(va,fmt);
-       vsnprintf(_DEBUGF_TMP,sizeof(_DEBUGF_TMP),fmt,va);
-       _DEBUG(_DEBUGF_TMP);
-       va_end(va);
-}
-#endif
-
+\r
+#include "src/16.h"\r
+\r
+// TODO: Could we also provide a build mode to emit debug to the "Bochs E9 hack?"\r
+#ifdef DEBUGSERIAL\r
+# include <stdarg.h>\r
+# include <stdlib.h>\r
+# include <stdio.h>\r
+\r
+unsigned char _DEBUG_INITed = 0;\r
+struct info_8250 *_DEBUG_uart = NULL;\r
+\r
+int _DEBUG_INIT() {\r
+       if (!_DEBUG_INITed) {\r
+               unsigned int i;\r
+               uint16_t port;\r
+\r
+               if (!init_8250()) return 0;\r
+\r
+               // what does the BIOS say the serial ports are?\r
+               probe_8250_bios_ports();\r
+               for (i=0;i < bios_8250_ports;i++) {\r
+                       port = get_8250_bios_port(i);\r
+                       if (port == 0) continue;\r
+                       probe_8250(port);\r
+               }\r
+\r
+               // what about the standard serial ports?\r
+               for (i=0;i < (sizeof(standard_8250_ports)/sizeof(standard_8250_ports[0]));i++) {\r
+                       port = standard_8250_ports[i];\r
+                       if (port == 0) continue;\r
+                       probe_8250(port);\r
+               }\r
+\r
+               // pick the first port, which is probably COM1\r
+               if (base_8250_ports == 0) return 0; // FIXME: You know "base_8250_ports" is probably a bad variable name for the max entries in info_8250_port[]\r
+               _DEBUG_uart = &info_8250_port[0];\r
+               _DEBUG_INITed = 1;\r
+\r
+               // init the COM port.\r
+               // in DOSBox-X, the "log" mode will receive our text and print it into the log file\r
+               // on real hardware, our text will likely go over a null modem cable to another PC running a serial terminal program like PuTTY or minicom.\r
+               // if nothing is connected, then the bytes go off into the ether to get lost and life goes on.\r
+               uart_8250_enable_interrupt(_DEBUG_uart,0);      // disable interrupts\r
+               uart_8250_set_FIFO(_DEBUG_uart,0x07);           // enable FIFO (why not?), also clear xmit/recv FIFO buffers, set threshhold to 1 byte\r
+               uart_8250_set_MCR(_DEBUG_uart,3);               // RTS and DTS on\r
+               uart_8250_set_line_control(_DEBUG_uart,UART_8250_LCR_8BIT | UART_8250_LCR_PARITY); // 8 bit 1 stop bit odd parity\r
+               uart_8250_set_baudrate(_DEBUG_uart,uart_8250_baud_to_divisor(_DEBUG_uart,9600)); // 9600 baud\r
+       }\r
+\r
+       return _DEBUG_INITed;\r
+}\r
+\r
+void _DEBUG(const char *msg) {\r
+       if (_DEBUG_uart != NULL) {\r
+               char c;\r
+\r
+               while ((c=(*msg++)) != 0/*NUL*/) {\r
+                       while (!uart_8250_can_write(_DEBUG_uart)); // wait for the UART to indicate readiness for our output\r
+                       uart_8250_write(_DEBUG_uart,(uint8_t)c); // then write it\r
+               }\r
+       }\r
+}\r
+\r
+static char _DEBUGF_TMP[256];\r
+\r
+void _DEBUGF(const char *fmt,...) {\r
+       va_list va;\r
+\r
+       va_start(va,fmt);\r
+       vsnprintf(_DEBUGF_TMP,sizeof(_DEBUGF_TMP),fmt,va);\r
+       _DEBUG(_DEBUGF_TMP);\r
+       va_end(va);\r
+}\r
+#endif\r
+\r
index 9aaf9644c1757ef922bec2c51c10d536e9dd290a..58c5a05a33b0f3ecb5f0b9f278dc6a2fa8c728f2 100755 (executable)
@@ -1,25 +1,25 @@
-
-#ifndef _SRC_LIB_16_DBG
-#define _SRC_LIB_16_DBG
-
-# ifdef DEBUGSERIAL
-#  include <hw/8250/8250.h>
-
-void _DEBUGF(const char *fmt,...);
-void _DEBUG(const char *msg);
-int _DEBUG_INIT();
-# else
-static inline void _DEBUGF(const char *fmt,...) {
-       // NOTHING
-}
-static inline void _DEBUG(const char *msg) {
-       // NOTHING
-}
-
-static inline int _DEBUG_INIT() {
-       // NOTHING
-       return -1;
-}
-# endif
-#endif // _SRC_LIB_16_DBG
-
+\r
+#ifndef _SRC_LIB_16_DBG\r
+#define _SRC_LIB_16_DBG\r
+\r
+# ifdef DEBUGSERIAL\r
+#  include <hw/8250/8250.h>\r
+\r
+void _DEBUGF(const char *fmt,...);\r
+void _DEBUG(const char *msg);\r
+int _DEBUG_INIT();\r
+# else\r
+static inline void _DEBUGF(const char *fmt,...) {\r
+       // NOTHING\r
+}\r
+static inline void _DEBUG(const char *msg) {\r
+       // NOTHING\r
+}\r
+\r
+static inline int _DEBUG_INIT() {\r
+       // NOTHING\r
+       return -1;\r
+}\r
+# endif\r
+#endif // _SRC_LIB_16_DBG\r
+\r
index 8743a38dc51e8fb479e1547ea99061ec128b0442..13dd3f0e5addcc9080dd48417d188bd1e086f695 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/*
-       heap test stuff
-*/
-
-#include "src/lib/16_hc.h"
-
-#ifdef __BORLANDC__
-void * LargestFreeBlock(size_t* Size)
-#endif
-#ifdef __WATCOMC__
-void __near* LargestFreeBlock(size_t* Size)
-#endif
-{
-       size_t s0, s1;
-#ifdef __BORLANDC__
-       void * p;
-#endif
-#ifdef __WATCOMC__
-       void __near* p;
-#endif
-
-       s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
-#ifdef __BORLANDC__
-       while (s0 && (p = malloc(s0)) == NULL)
-#endif
-#ifdef __WATCOMC__
-       while (s0 && (p = _nmalloc(s0)) == NULL)
-#endif
-               s0 >>= 1;
-
-       if (p)
-#ifdef __BORLANDC__
-               free(p);
-#endif
-#ifdef __WATCOMC__
-               _nfree(p);
-#endif
-
-       s1 = s0 >> 1;
-       while (s1)
-       {
-#ifdef __BORLANDC__
-               if ((p = malloc(s0 + s1)) != NULL)
-#endif
-#ifdef __WATCOMC__
-               if ((p = _nmalloc(s0 + s1)) != NULL)
-#endif
-               {
-                       s0 += s1;
-#ifdef __BORLANDC__
-                       free(p);
-#endif
-#ifdef __WATCOMC__
-                       _nfree(p);
-#endif
-               }
-       s1 >>= 1;
-       }
-#ifdef __BORLANDC__
-       while (s0 && (p = malloc(s0)) == NULL)
-#endif
-#ifdef __WATCOMC__
-       while (s0 && (p = _nmalloc(s0)) == NULL)
-#endif
-               s0 ^= s0 & -s0;
-
-       *Size = s0;
-       return p;
-}
-
-size_t _coreleft(void)
-{
-       size_t total = 0;
-       void __near* pFirst = NULL;
-       void __near* pLast = NULL;
-       for(;;)
-       {
-               size_t largest;
-               void __near* p = (void __near *)LargestFreeBlock(&largest);
-               if (largest < sizeof(void __near*))
-               {
-                       if (p != NULL)
-#ifdef __BORLANDC__
-                       free(p);
-#endif
-#ifdef __WATCOMC__
-                       _nfree(p);
-#endif
-                       break;
-               }
-               *(void __near* __near*)p = NULL;
-               total += largest;
-               if (pFirst == NULL)
-                       pFirst = p;
-
-               if (pLast != NULL)
-                       *(void __near* __near*)pLast = p;
-               pLast = p;
-       }
-
-       while (pFirst != NULL)
-       {
-               void __near* p = *(void __near* __near*)pFirst;
-#ifdef __BORLANDC__
-               free(pFirst);
-#endif
-#ifdef __WATCOMC__
-               _nfree(pFirst);
-#endif
-               pFirst = p;
-       }
-       return total;
-}
-
-void far* LargestFarFreeBlock(size_t* Size)
-{
-       size_t s0, s1;
-       void far* p;
-
-       s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
-       while (s0 && (p = _fmalloc(s0)) == NULL)
-               s0 >>= 1;
-
-       if (p)
-               _ffree(p);
-
-       s1 = s0 >> 1;
-       while (s1)
-       {
-               if ((p = _fmalloc(s0 + s1)) != NULL)
-               {
-                       s0 += s1;
-                       _ffree(p);
-               }
-       s1 >>= 1;
-       }
-       while (s0 && (p = _fmalloc(s0)) == NULL)
-               s0 ^= s0 & -s0;
-
-       *Size = s0;
-       return p;
-}
-
-size_t _farcoreleft(void)
-{
-       size_t total = 0;
-       void far* pFirst = NULL;
-       void far* pLast = NULL;
-       for(;;)
-       {
-               size_t largest;
-               void far* p = LargestFarFreeBlock(&largest);
-               if (largest < sizeof(void far*))
-               {
-                       if (p != NULL)
-                       _ffree(p);
-                       break;
-               }
-               *(void far* far*)p = NULL;
-               total += largest;
-               if (pFirst == NULL)
-                       pFirst = p;
-
-               if (pLast != NULL)
-                       *(void far* far*)pLast = p;
-               pLast = p;
-       }
-
-       while (pFirst != NULL)
-       {
-               void far* p = *(void far* far*)pFirst;
-               _ffree(pFirst);
-               pFirst = p;
-       }
-       return total;
-}
-
-#ifdef __WATCOMC__
-void huge* LargestHugeFreeBlock(size_t* Size)
-{
-       size_t s0, s1;
-       void huge* p;
-
-       s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
-       while (s0 && (p = halloc((dword)s0, 1)) == NULL)
-               s0 >>= 1;
-
-       if (p)
-               hfree(p);
-
-       s1 = s0 >> 1;
-       while (s1)
-       {
-               if ((p = halloc((dword)(s0 + s1), 1)) != NULL)
-               {
-                       s0 += s1;
-                       hfree(p);
-               }
-       s1 >>= 1;
-       }
-       while (s0 && (p = halloc((dword)s0, 1)) == NULL)
-               s0 ^= s0 & -s0;
-
-       *Size = s0;
-       return p;
-}
-
-size_t _hugecoreleft(void)
-{
-       size_t total = 0;
-       void huge* pFirst = NULL;
-       void huge* pLast = NULL;
-       for(;;)
-       {
-               size_t largest;
-               void huge* p = LargestHugeFreeBlock(&largest);
-               if (largest < sizeof(void huge*))
-               {
-                       if (p != NULL)
-                       hfree(p);
-                       break;
-               }
-               *(void huge* huge*)p = NULL;
-               total += largest;
-               if (pFirst == NULL)
-                       pFirst = p;
-
-               if (pLast != NULL)
-                       *(void huge* huge*)pLast = p;
-               pLast = p;
-       }
-
-       while (pFirst != NULL)
-       {
-               void huge* p = *(void huge* huge*)pFirst;
-               hfree(pFirst);
-               pFirst = p;
-       }
-       return total;
-}
-
-/*void __based(__self)* LargestBasedFreeBlock(size_t* Size)
-{
-       __segment segu;
-       size_t s0, s1;
-       void __based(__self)* p;
-
-       s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
-       while (s0 && (p = _bmalloc(segu, s0)) == NULL)
-               s0 >>= 1;
-
-       if (p)
-               _ffree(p);
-
-       s1 = s0 >> 1;
-       while (s1)
-       {
-               if ((p = _bmalloc(segu, s0 + s1)) != NULL)
-               {
-                       s0 += s1;
-                       _ffree(p);
-               }
-       s1 >>= 1;
-       }
-       while (s0 && (p = _bmalloc(segu, s0)) == NULL)
-               s0 ^= s0 & -s0;
-
-       *Size = s0;
-       return p;
-}
-
-size_t _basedcoreleft(void)
-{
-       __segment segu;
-       size_t total = 0;
-       void __based(segu)* pFirst = NULL;
-       void __based(segu)* pLast = NULL;
-       // allocate based heap
-       segu = _bheapseg( 1024 );
-       if( segu == _NULLSEG ) {
-               printf( "Unable to allocate based heap\n" );
-               return 0;
-               //exit( 1 );
-       }
-       else
-
-       for(;;)
-       {
-               size_t largest;
-               void __based(segu)* p = LargestBasedFreeBlock(&largest);
-               if (largest < sizeof(void far*))
-               {
-                       if (p != NULL)
-                       _ffree(p);
-                       break;
-               }
-               *(void far* far*)p = NULL;
-               total += largest;
-               if (pFirst == NULL)
-                       pFirst = p;
-
-               if (pLast != NULL)
-                       *(void far* far*)pLast = p;
-               pLast = p;
-       }
-
-       while (pFirst != NULL)
-       {
-               void far* p = *(void far* far*)pFirst;
-               _ffree(pFirst);
-               pFirst = p;
-       }
-       return total;
-}*/
-
-size_t GetFreeSize(void)
-{
-       struct _heapinfo h_info;
-       int heap_status;
-       size_t h_free=0, h_total=0, h_used=0;
-
-       h_info._pentry = NULL;
-       for(;;) {
-               heap_status = _heapwalk( &h_info );
-               if( heap_status != _HEAPOK ) break;
-               if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size;
-               if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size;
-               h_total += h_info._size;
-       }
-       heapstat0(heap_status);
-       return h_free;
-}
-
-size_t GetFarFreeSize(void)
-{
-       struct _heapinfo fh_info;
-       int heap_status;
-       size_t fh_free=0, fh_total=0, fh_used=0;
-
-       fh_info._pentry = NULL;
-       for(;;) {
-               heap_status = _fheapwalk( &fh_info );
-               if( heap_status != _HEAPOK ) break;
-               if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size;
-               if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size;
-               fh_total += fh_info._size;
-       }
-       heapstat0(heap_status);
-       return fh_free;
-}
-
-size_t GetNearFreeSize(void)
-{
-       struct _heapinfo nh_info;
-       int heap_status;
-       size_t nh_free=0, nh_total=0, nh_used=0;
-
-       nh_info._pentry = NULL;
-       for(;;) {
-               heap_status = _nheapwalk( &nh_info );
-               if( heap_status != _HEAPOK ) break;
-               if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size;
-               if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size;
-               nh_total += nh_info._size;
-       }
-       heapstat0(heap_status);
-       return nh_free;
-}
-
-void heapdump(global_game_variables_t *gvar)
-{
-       struct _heapinfo fh_info, nh_info, h_info;
-       int heap_status;
-       size_t h_free, nh_free, fh_free, h_total, nh_total, fh_total, h_used, nh_used, fh_used;
-       byte    scratch[1024],str[16];
-
-       HC_OpenDebug(gvar);
-
-       strcpy(scratch,"\n      == default ==\n\n");
-       write(gvar->handle.heaphandle,scratch,strlen(scratch));
-       h_info._pentry = NULL;
-       h_free=0; h_total=0; h_used=0;
-       for(;;) {
-               heap_status = _heapwalk( &h_info );
-               if( heap_status != _HEAPOK ) break;
-               strcpy(scratch,"  "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)h_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(h_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");
-               if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size;
-               if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size;
-               h_total += h_info._size;
-               write(gvar->handle.heaphandle,scratch,strlen(scratch));
-       }
-       heapstat(gvar, heap_status, &scratch);
-
-       //near
-       strcpy(scratch,"\n      == near ==\n\n");
-       write(gvar->handle.heaphandle,scratch,strlen(scratch));
-       nh_info._pentry = NULL;
-       nh_free=0; nh_total=0; nh_used=0;
-       for(;;) {
-               heap_status = _nheapwalk( &nh_info );
-               if( heap_status != _HEAPOK ) break;
-               strcpy(scratch,"  "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)nh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(nh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");
-/*             printf( "  %s block at %Fp of size %4.4X\n",
-(nh_info._useflag == _USEDENTRY ? "USED" : "FREE"),
-nh_info._pentry, nh_info._size );*/
-               if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size;
-               if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size;
-               nh_total += nh_info._size;
-               write(gvar->handle.heaphandle,scratch,strlen(scratch));
-       }
-       heapstat(gvar, heap_status, &scratch);
-
-       //far
-       strcpy(scratch,"\n      == far ==\n\n");
-       write(gvar->handle.heaphandle,scratch,strlen(scratch));
-       fh_info._pentry = NULL;
-       fh_free=0; fh_total=0; fh_used=0;
-       for(;;) {
-               heap_status = _fheapwalk( &fh_info );
-               if( heap_status != _HEAPOK ) break;
-               strcpy(scratch,"  "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)fh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(fh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");
-               /*printf( "  %s block at %Fp of size %4.4X\n",
-(fh_info._useflag == _USEDENTRY ? "USED" : "FREE"),
-fh_info._pentry, fh_info._size );*/
-               if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size;
-               if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size;
-               fh_total += fh_info._size;
-               write(gvar->handle.heaphandle,scratch,strlen(scratch));
-       }
-       heapstat(gvar, heap_status, &scratch);
-
-       strcpy(scratch,"\n");
-       strcat(scratch,kittengets(2,0,"Memory Type         Total      Used       Free\n"));
-       strcat(scratch,"----------------  --------   --------   --------\n");
-       printmeminfoline(&scratch, "Default", h_total, h_used, h_free);
-       printmeminfoline(&scratch, "Near", nh_total, nh_used, nh_free);
-       printmeminfoline(&scratch, "Far", fh_total, fh_used, fh_free);
-       strcat(scratch,"----------------  --------   --------   --------\n");
-       strcat(scratch,"coreleft = ");                  ultoa((dword)_coreleft(),str,10);               strcat(scratch,str);    strcat(scratch,"\n");
-       strcat(scratch,"farcoreleft = ");               ultoa((dword)_farcoreleft(),str,10);    strcat(scratch,str);    strcat(scratch,"\n");
-       strcat(scratch,"GetFreeSize = ");               ultoa((dword)GetFreeSize(),str,10);             strcat(scratch,str);    strcat(scratch,"\n");
-       strcat(scratch,"GetNearFreeSize = ");   ultoa((dword)GetNearFreeSize(),str,10); strcat(scratch,str);    strcat(scratch,"\n");
-       strcat(scratch,"GetFarFreeSize = ");    ultoa((dword)GetFarFreeSize(),str,10);  strcat(scratch,str);    strcat(scratch,"\n");
-       strcat(scratch,"memavl = ");                    ultoa((dword)_memavl(),str,10);                 strcat(scratch,str);    strcat(scratch,"\n");
-       strcat(scratch,"stackavail = ");                ultoa((dword)stackavail(),str,10);              strcat(scratch,str);    strcat(scratch,"\n");
-       write(gvar->handle.heaphandle,scratch,strlen(scratch));
-       HC_CloseDebug(gvar);
-}
-
-void heapstat(global_game_variables_t *gvar, int heap_status, byte *str)
-{
-       switch( heap_status ) {
-               case _HEAPEND:
-                       strcpy((str),"OK - end of heap\n");
-               break;
-               case _HEAPEMPTY:
-                       strcpy((str),"OK - heap is empty\n");
-
-               break;
-               case _HEAPBADBEGIN:
-                       strcpy((str),"ERROR - heap is damaged\n");
-               break;
-               case _HEAPBADPTR:
-                       strcpy((str),"ERROR - bad pointer to heap\n");
-               break;
-               case _HEAPBADNODE:
-                       strcpy((str),"ERROR - bad node in heap\n");
-       }
-       write(gvar->handle.heaphandle,(str),strlen((str)));
-}
-
-void heapstat0(int heap_status)
-{
-       switch( heap_status ) {
-               case _HEAPEND:
-                       //printf("OK - end of heap\n");
-               break;
-               case _HEAPEMPTY:
-                       //printf("OK - heap is empty\n");
-               break;
-               case _HEAPBADBEGIN:
-                       printf("ERROR - heap is damaged\n");
-               break;
-               case _HEAPBADPTR:
-                       printf("ERROR - bad pointer to heap\n");
-               break;
-               case _HEAPBADNODE:
-                       printf("ERROR - bad node in heap\n");
-       }
-}
-#endif
-/*
-============================
-=
-= HC_OpenDebug / HC_CloseDebug
-=
-= Opens a binary file with the handle "heaphandle"
-=
-============================
-*/
-void HC_OpenDebug(global_game_variables_t *gvar)
-{
-#ifdef __BORLANDC__
-       unlink("heap.16b");
-       gvar->handle.heaphandle = open("heap.16b", O_CREAT | O_WRONLY | O_TEXT);
-#endif
-#ifdef __WATCOMC__
-       unlink("heap.16w");
-       gvar->handle.heaphandle = open("heap.16w", O_CREAT | O_WRONLY | O_TEXT);
-#endif
-}
-
-void HC_CloseDebug(global_game_variables_t *gvar)
-{
-       close(gvar->handle.heaphandle);
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+/*\r
+       heap test stuff\r
+*/\r
+\r
+#include "src/lib/16_hc.h"\r
+\r
+#ifdef __BORLANDC__\r
+void * LargestFreeBlock(size_t* Size)\r
+#endif\r
+#ifdef __WATCOMC__\r
+void __near* LargestFreeBlock(size_t* Size)\r
+#endif\r
+{\r
+       size_t s0, s1;\r
+#ifdef __BORLANDC__\r
+       void * p;\r
+#endif\r
+#ifdef __WATCOMC__\r
+       void __near* p;\r
+#endif\r
+\r
+       s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);\r
+#ifdef __BORLANDC__\r
+       while (s0 && (p = malloc(s0)) == NULL)\r
+#endif\r
+#ifdef __WATCOMC__\r
+       while (s0 && (p = _nmalloc(s0)) == NULL)\r
+#endif\r
+               s0 >>= 1;\r
+\r
+       if (p)\r
+#ifdef __BORLANDC__\r
+               free(p);\r
+#endif\r
+#ifdef __WATCOMC__\r
+               _nfree(p);\r
+#endif\r
+\r
+       s1 = s0 >> 1;\r
+       while (s1)\r
+       {\r
+#ifdef __BORLANDC__\r
+               if ((p = malloc(s0 + s1)) != NULL)\r
+#endif\r
+#ifdef __WATCOMC__\r
+               if ((p = _nmalloc(s0 + s1)) != NULL)\r
+#endif\r
+               {\r
+                       s0 += s1;\r
+#ifdef __BORLANDC__\r
+                       free(p);\r
+#endif\r
+#ifdef __WATCOMC__\r
+                       _nfree(p);\r
+#endif\r
+               }\r
+       s1 >>= 1;\r
+       }\r
+#ifdef __BORLANDC__\r
+       while (s0 && (p = malloc(s0)) == NULL)\r
+#endif\r
+#ifdef __WATCOMC__\r
+       while (s0 && (p = _nmalloc(s0)) == NULL)\r
+#endif\r
+               s0 ^= s0 & -s0;\r
+\r
+       *Size = s0;\r
+       return p;\r
+}\r
+\r
+size_t _coreleft(void)\r
+{\r
+       size_t total = 0;\r
+       void __near* pFirst = NULL;\r
+       void __near* pLast = NULL;\r
+       for(;;)\r
+       {\r
+               size_t largest;\r
+               void __near* p = (void __near *)LargestFreeBlock(&largest);\r
+               if (largest < sizeof(void __near*))\r
+               {\r
+                       if (p != NULL)\r
+#ifdef __BORLANDC__\r
+                       free(p);\r
+#endif\r
+#ifdef __WATCOMC__\r
+                       _nfree(p);\r
+#endif\r
+                       break;\r
+               }\r
+               *(void __near* __near*)p = NULL;\r
+               total += largest;\r
+               if (pFirst == NULL)\r
+                       pFirst = p;\r
+\r
+               if (pLast != NULL)\r
+                       *(void __near* __near*)pLast = p;\r
+               pLast = p;\r
+       }\r
+\r
+       while (pFirst != NULL)\r
+       {\r
+               void __near* p = *(void __near* __near*)pFirst;\r
+#ifdef __BORLANDC__\r
+               free(pFirst);\r
+#endif\r
+#ifdef __WATCOMC__\r
+               _nfree(pFirst);\r
+#endif\r
+               pFirst = p;\r
+       }\r
+       return total;\r
+}\r
+\r
+void far* LargestFarFreeBlock(size_t* Size)\r
+{\r
+       size_t s0, s1;\r
+       void far* p;\r
+\r
+       s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);\r
+       while (s0 && (p = _fmalloc(s0)) == NULL)\r
+               s0 >>= 1;\r
+\r
+       if (p)\r
+               _ffree(p);\r
+\r
+       s1 = s0 >> 1;\r
+       while (s1)\r
+       {\r
+               if ((p = _fmalloc(s0 + s1)) != NULL)\r
+               {\r
+                       s0 += s1;\r
+                       _ffree(p);\r
+               }\r
+       s1 >>= 1;\r
+       }\r
+       while (s0 && (p = _fmalloc(s0)) == NULL)\r
+               s0 ^= s0 & -s0;\r
+\r
+       *Size = s0;\r
+       return p;\r
+}\r
+\r
+size_t _farcoreleft(void)\r
+{\r
+       size_t total = 0;\r
+       void far* pFirst = NULL;\r
+       void far* pLast = NULL;\r
+       for(;;)\r
+       {\r
+               size_t largest;\r
+               void far* p = LargestFarFreeBlock(&largest);\r
+               if (largest < sizeof(void far*))\r
+               {\r
+                       if (p != NULL)\r
+                       _ffree(p);\r
+                       break;\r
+               }\r
+               *(void far* far*)p = NULL;\r
+               total += largest;\r
+               if (pFirst == NULL)\r
+                       pFirst = p;\r
+\r
+               if (pLast != NULL)\r
+                       *(void far* far*)pLast = p;\r
+               pLast = p;\r
+       }\r
+\r
+       while (pFirst != NULL)\r
+       {\r
+               void far* p = *(void far* far*)pFirst;\r
+               _ffree(pFirst);\r
+               pFirst = p;\r
+       }\r
+       return total;\r
+}\r
+\r
+#ifdef __WATCOMC__\r
+void huge* LargestHugeFreeBlock(size_t* Size)\r
+{\r
+       size_t s0, s1;\r
+       void huge* p;\r
+\r
+       s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);\r
+       while (s0 && (p = halloc((dword)s0, 1)) == NULL)\r
+               s0 >>= 1;\r
+\r
+       if (p)\r
+               hfree(p);\r
+\r
+       s1 = s0 >> 1;\r
+       while (s1)\r
+       {\r
+               if ((p = halloc((dword)(s0 + s1), 1)) != NULL)\r
+               {\r
+                       s0 += s1;\r
+                       hfree(p);\r
+               }\r
+       s1 >>= 1;\r
+       }\r
+       while (s0 && (p = halloc((dword)s0, 1)) == NULL)\r
+               s0 ^= s0 & -s0;\r
+\r
+       *Size = s0;\r
+       return p;\r
+}\r
+\r
+size_t _hugecoreleft(void)\r
+{\r
+       size_t total = 0;\r
+       void huge* pFirst = NULL;\r
+       void huge* pLast = NULL;\r
+       for(;;)\r
+       {\r
+               size_t largest;\r
+               void huge* p = LargestHugeFreeBlock(&largest);\r
+               if (largest < sizeof(void huge*))\r
+               {\r
+                       if (p != NULL)\r
+                       hfree(p);\r
+                       break;\r
+               }\r
+               *(void huge* huge*)p = NULL;\r
+               total += largest;\r
+               if (pFirst == NULL)\r
+                       pFirst = p;\r
+\r
+               if (pLast != NULL)\r
+                       *(void huge* huge*)pLast = p;\r
+               pLast = p;\r
+       }\r
+\r
+       while (pFirst != NULL)\r
+       {\r
+               void huge* p = *(void huge* huge*)pFirst;\r
+               hfree(pFirst);\r
+               pFirst = p;\r
+       }\r
+       return total;\r
+}\r
+\r
+/*void __based(__self)* LargestBasedFreeBlock(size_t* Size)\r
+{\r
+       __segment segu;\r
+       size_t s0, s1;\r
+       void __based(__self)* p;\r
+\r
+       s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);\r
+       while (s0 && (p = _bmalloc(segu, s0)) == NULL)\r
+               s0 >>= 1;\r
+\r
+       if (p)\r
+               _ffree(p);\r
+\r
+       s1 = s0 >> 1;\r
+       while (s1)\r
+       {\r
+               if ((p = _bmalloc(segu, s0 + s1)) != NULL)\r
+               {\r
+                       s0 += s1;\r
+                       _ffree(p);\r
+               }\r
+       s1 >>= 1;\r
+       }\r
+       while (s0 && (p = _bmalloc(segu, s0)) == NULL)\r
+               s0 ^= s0 & -s0;\r
+\r
+       *Size = s0;\r
+       return p;\r
+}\r
+\r
+size_t _basedcoreleft(void)\r
+{\r
+       __segment segu;\r
+       size_t total = 0;\r
+       void __based(segu)* pFirst = NULL;\r
+       void __based(segu)* pLast = NULL;\r
+       // allocate based heap\r
+       segu = _bheapseg( 1024 );\r
+       if( segu == _NULLSEG ) {\r
+               printf( "Unable to allocate based heap\n" );\r
+               return 0;\r
+               //exit( 1 );\r
+       }\r
+       else\r
+\r
+       for(;;)\r
+       {\r
+               size_t largest;\r
+               void __based(segu)* p = LargestBasedFreeBlock(&largest);\r
+               if (largest < sizeof(void far*))\r
+               {\r
+                       if (p != NULL)\r
+                       _ffree(p);\r
+                       break;\r
+               }\r
+               *(void far* far*)p = NULL;\r
+               total += largest;\r
+               if (pFirst == NULL)\r
+                       pFirst = p;\r
+\r
+               if (pLast != NULL)\r
+                       *(void far* far*)pLast = p;\r
+               pLast = p;\r
+       }\r
+\r
+       while (pFirst != NULL)\r
+       {\r
+               void far* p = *(void far* far*)pFirst;\r
+               _ffree(pFirst);\r
+               pFirst = p;\r
+       }\r
+       return total;\r
+}*/\r
+\r
+size_t GetFreeSize(void)\r
+{\r
+       struct _heapinfo h_info;\r
+       int heap_status;\r
+       size_t h_free=0, h_total=0, h_used=0;\r
+\r
+       h_info._pentry = NULL;\r
+       for(;;) {\r
+               heap_status = _heapwalk( &h_info );\r
+               if( heap_status != _HEAPOK ) break;\r
+               if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size;\r
+               if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size;\r
+               h_total += h_info._size;\r
+       }\r
+       heapstat0(heap_status);\r
+       return h_free;\r
+}\r
+\r
+size_t GetFarFreeSize(void)\r
+{\r
+       struct _heapinfo fh_info;\r
+       int heap_status;\r
+       size_t fh_free=0, fh_total=0, fh_used=0;\r
+\r
+       fh_info._pentry = NULL;\r
+       for(;;) {\r
+               heap_status = _fheapwalk( &fh_info );\r
+               if( heap_status != _HEAPOK ) break;\r
+               if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size;\r
+               if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size;\r
+               fh_total += fh_info._size;\r
+       }\r
+       heapstat0(heap_status);\r
+       return fh_free;\r
+}\r
+\r
+size_t GetNearFreeSize(void)\r
+{\r
+       struct _heapinfo nh_info;\r
+       int heap_status;\r
+       size_t nh_free=0, nh_total=0, nh_used=0;\r
+\r
+       nh_info._pentry = NULL;\r
+       for(;;) {\r
+               heap_status = _nheapwalk( &nh_info );\r
+               if( heap_status != _HEAPOK ) break;\r
+               if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size;\r
+               if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size;\r
+               nh_total += nh_info._size;\r
+       }\r
+       heapstat0(heap_status);\r
+       return nh_free;\r
+}\r
+\r
+void heapdump(global_game_variables_t *gvar)\r
+{\r
+       struct _heapinfo fh_info, nh_info, h_info;\r
+       int heap_status;\r
+       size_t h_free, nh_free, fh_free, h_total, nh_total, fh_total, h_used, nh_used, fh_used;\r
+       byte    scratch[1024],str[16];\r
+\r
+       HC_OpenDebug(gvar);\r
+\r
+       strcpy(scratch,"\n      == default ==\n\n");\r
+       write(gvar->handle.heaphandle,scratch,strlen(scratch));\r
+       h_info._pentry = NULL;\r
+       h_free=0; h_total=0; h_used=0;\r
+       for(;;) {\r
+               heap_status = _heapwalk( &h_info );\r
+               if( heap_status != _HEAPOK ) break;\r
+               strcpy(scratch,"  "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)h_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(h_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");\r
+               if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size;\r
+               if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size;\r
+               h_total += h_info._size;\r
+               write(gvar->handle.heaphandle,scratch,strlen(scratch));\r
+       }\r
+       heapstat(gvar, heap_status, &scratch);\r
+\r
+       //near\r
+       strcpy(scratch,"\n      == near ==\n\n");\r
+       write(gvar->handle.heaphandle,scratch,strlen(scratch));\r
+       nh_info._pentry = NULL;\r
+       nh_free=0; nh_total=0; nh_used=0;\r
+       for(;;) {\r
+               heap_status = _nheapwalk( &nh_info );\r
+               if( heap_status != _HEAPOK ) break;\r
+               strcpy(scratch,"  "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)nh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(nh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");\r
+/*             printf( "  %s block at %Fp of size %4.4X\n",\r
+(nh_info._useflag == _USEDENTRY ? "USED" : "FREE"),\r
+nh_info._pentry, nh_info._size );*/\r
+               if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size;\r
+               if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size;\r
+               nh_total += nh_info._size;\r
+               write(gvar->handle.heaphandle,scratch,strlen(scratch));\r
+       }\r
+       heapstat(gvar, heap_status, &scratch);\r
+\r
+       //far\r
+       strcpy(scratch,"\n      == far ==\n\n");\r
+       write(gvar->handle.heaphandle,scratch,strlen(scratch));\r
+       fh_info._pentry = NULL;\r
+       fh_free=0; fh_total=0; fh_used=0;\r
+       for(;;) {\r
+               heap_status = _fheapwalk( &fh_info );\r
+               if( heap_status != _HEAPOK ) break;\r
+               strcpy(scratch,"  "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)fh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(fh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");\r
+               /*printf( "  %s block at %Fp of size %4.4X\n",\r
+(fh_info._useflag == _USEDENTRY ? "USED" : "FREE"),\r
+fh_info._pentry, fh_info._size );*/\r
+               if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size;\r
+               if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size;\r
+               fh_total += fh_info._size;\r
+               write(gvar->handle.heaphandle,scratch,strlen(scratch));\r
+       }\r
+       heapstat(gvar, heap_status, &scratch);\r
+\r
+       strcpy(scratch,"\n");\r
+       strcat(scratch,kittengets(2,0,"Memory Type         Total      Used       Free\n"));\r
+       strcat(scratch,"----------------  --------   --------   --------\n");\r
+       printmeminfoline(&scratch, "Default", h_total, h_used, h_free);\r
+       printmeminfoline(&scratch, "Near", nh_total, nh_used, nh_free);\r
+       printmeminfoline(&scratch, "Far", fh_total, fh_used, fh_free);\r
+       strcat(scratch,"----------------  --------   --------   --------\n");\r
+       strcat(scratch,"coreleft = ");                  ultoa((dword)_coreleft(),str,10);               strcat(scratch,str);    strcat(scratch,"\n");\r
+       strcat(scratch,"farcoreleft = ");               ultoa((dword)_farcoreleft(),str,10);    strcat(scratch,str);    strcat(scratch,"\n");\r
+       strcat(scratch,"GetFreeSize = ");               ultoa((dword)GetFreeSize(),str,10);             strcat(scratch,str);    strcat(scratch,"\n");\r
+       strcat(scratch,"GetNearFreeSize = ");   ultoa((dword)GetNearFreeSize(),str,10); strcat(scratch,str);    strcat(scratch,"\n");\r
+       strcat(scratch,"GetFarFreeSize = ");    ultoa((dword)GetFarFreeSize(),str,10);  strcat(scratch,str);    strcat(scratch,"\n");\r
+       strcat(scratch,"memavl = ");                    ultoa((dword)_memavl(),str,10);                 strcat(scratch,str);    strcat(scratch,"\n");\r
+       strcat(scratch,"stackavail = ");                ultoa((dword)stackavail(),str,10);              strcat(scratch,str);    strcat(scratch,"\n");\r
+       write(gvar->handle.heaphandle,scratch,strlen(scratch));\r
+       HC_CloseDebug(gvar);\r
+}\r
+\r
+void heapstat(global_game_variables_t *gvar, int heap_status, byte *str)\r
+{\r
+       switch( heap_status ) {\r
+               case _HEAPEND:\r
+                       strcpy((str),"OK - end of heap\n");\r
+               break;\r
+               case _HEAPEMPTY:\r
+                       strcpy((str),"OK - heap is empty\n");\r
+\r
+               break;\r
+               case _HEAPBADBEGIN:\r
+                       strcpy((str),"ERROR - heap is damaged\n");\r
+               break;\r
+               case _HEAPBADPTR:\r
+                       strcpy((str),"ERROR - bad pointer to heap\n");\r
+               break;\r
+               case _HEAPBADNODE:\r
+                       strcpy((str),"ERROR - bad node in heap\n");\r
+       }\r
+       write(gvar->handle.heaphandle,(str),strlen((str)));\r
+}\r
+\r
+void heapstat0(int heap_status)\r
+{\r
+       switch( heap_status ) {\r
+               case _HEAPEND:\r
+                       //printf("OK - end of heap\n");\r
+               break;\r
+               case _HEAPEMPTY:\r
+                       //printf("OK - heap is empty\n");\r
+               break;\r
+               case _HEAPBADBEGIN:\r
+                       printf("ERROR - heap is damaged\n");\r
+               break;\r
+               case _HEAPBADPTR:\r
+                       printf("ERROR - bad pointer to heap\n");\r
+               break;\r
+               case _HEAPBADNODE:\r
+                       printf("ERROR - bad node in heap\n");\r
+       }\r
+}\r
+#endif\r
+/*\r
+============================\r
+=\r
+= HC_OpenDebug / HC_CloseDebug\r
+=\r
+= Opens a binary file with the handle "heaphandle"\r
+=\r
+============================\r
+*/\r
+void HC_OpenDebug(global_game_variables_t *gvar)\r
+{\r
+#ifdef __BORLANDC__\r
+       unlink("heap.16b");\r
+       gvar->handle.heaphandle = open("heap.16b", O_CREAT | O_WRONLY | O_TEXT);\r
+#endif\r
+#ifdef __WATCOMC__\r
+       unlink("heap.16w");\r
+       gvar->handle.heaphandle = open("heap.16w", O_CREAT | O_WRONLY | O_TEXT);\r
+#endif\r
+}\r
+\r
+void HC_CloseDebug(global_game_variables_t *gvar)\r
+{\r
+       close(gvar->handle.heaphandle);\r
+}\r
index 4d0375e2f72f96eeb779a593934abee2b9481d1a..870d50c7c89927a5f8e32e6ec716e0353771a221 100755 (executable)
@@ -1,54 +1,54 @@
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/*
-       heap test stuff
-*/
-
-#ifndef __16HC__
-#define __16HC__
-
-#include "src/lib/16_head.h"
-
-#ifdef __BORLANDC__
-void * LargestFreeBlock(size_t* Size);
-#endif
-#ifdef __WATCOMC__
-void __near* LargestFreeBlock(size_t* Size);
-#endif
-size_t _coreleft(void);
-void far* LargestFarFreeBlock(size_t* Size);
-size_t _farcoreleft(void);
-void huge* LargestHugeFreeBlock(size_t* Size);
-size_t _hugecoreleft(void);
-//void __based(__self)* LargestBasedFreeBlock(size_t* Size);
-//size_t _basedcoreleft(void);
-size_t GetFreeSize(void);
-size_t GetFarFreeSize(void);
-size_t GetNearFreeSize(void);
-void heapdump(global_game_variables_t *gvar);
-void heapstat(global_game_variables_t *gvar, int heap_status, byte *str);
-void heapstat0(int heap_status);
-
-void HC_OpenDebug(global_game_variables_t *gvar);
-void HC_CloseDebug(global_game_variables_t *gvar);
-
-#endif /* __16HC__ */
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+/*\r
+       heap test stuff\r
+*/\r
+\r
+#ifndef __16HC__\r
+#define __16HC__\r
+\r
+#include "src/lib/16_head.h"\r
+\r
+#ifdef __BORLANDC__\r
+void * LargestFreeBlock(size_t* Size);\r
+#endif\r
+#ifdef __WATCOMC__\r
+void __near* LargestFreeBlock(size_t* Size);\r
+#endif\r
+size_t _coreleft(void);\r
+void far* LargestFarFreeBlock(size_t* Size);\r
+size_t _farcoreleft(void);\r
+void huge* LargestHugeFreeBlock(size_t* Size);\r
+size_t _hugecoreleft(void);\r
+//void __based(__self)* LargestBasedFreeBlock(size_t* Size);\r
+//size_t _basedcoreleft(void);\r
+size_t GetFreeSize(void);\r
+size_t GetFarFreeSize(void);\r
+size_t GetNearFreeSize(void);\r
+void heapdump(global_game_variables_t *gvar);\r
+void heapstat(global_game_variables_t *gvar, int heap_status, byte *str);\r
+void heapstat0(int heap_status);\r
+\r
+void HC_OpenDebug(global_game_variables_t *gvar);\r
+void HC_CloseDebug(global_game_variables_t *gvar);\r
+\r
+#endif /* __16HC__ */\r
index 027693d501664062130bc257985efb7fb0ae715d..e56baa94bc86fb44c4efc521450b67d872afef18 100755 (executable)
 \r
 #include "src/lib/16_head.h"\r
 \r
-/* Function: Wait **********************************************************\r
-*\r
-*     Parameters:    wait - time in microseconds\r
-*\r
-*     Description:    pauses for a specified number of microseconds.\r
-*\r
-*/\r
-void wait(clock_t wait){\r
-       clock_t goal;\r
-\r
-       if(!wait) return;\r
-\r
-       goal = wait + clock();\r
-       while((goal > clock()) && !kbhit()) ;\r
-} /* End of wait */\r
-\r
 long int\r
 filesize(FILE *fp)\r
 {\r
@@ -94,6 +78,8 @@ US_CheckParm(char *parm,char **strings)
        }\r
        return(-1);\r
 }\r
+#ifdef __BORLANDC__\r
+//===========================================================================\r
 \r
 /*\r
 ==========================\r
@@ -103,61 +89,61 @@ US_CheckParm(char *parm,char **strings)
 ==========================\r
 */\r
 \r
-/*void Quit(char *error, ...)\r
+void Quit (char *error)\r
 {\r
-       short exit_code=0;\r
-       unsigned        finscreen;\r
-\r
-       va_list ap;\r
+       unsigned        finscreen;\r
+       memptr  screen;\r
+       union REGS in, out;\r
 \r
-       va_start(ap,error);\r
-\r
-#ifndef CATALOG\r
-       if (!error)\r
+       //ClearMemory ();\r
+       if (!*error)\r
        {\r
-               CA_SetAllPurge ();\r
-               CA_CacheGrChunk (PIRACY);\r
-               finscreen = (unsigned)grsegs[PIRACY];\r
+        //WriteConfig ();\r
+       }\r
+       else\r
+       {\r
+        //CA_CacheGrChunk (ERRORSCREEN);\r
+        //screen = grsegs[ERRORSCREEN];\r
        }\r
-#endif\r
 \r
        //ShutdownId ();\r
+       //IN_Shutdown();\r
+       //modexLeave();\r
+       in.h.ah = 0x00;\r
+       in.h.al = 0x3;\r
+       int86(0x10, &in, &out);\r
 \r
        if (error && *error)\r
        {\r
-               vprintf(error,ap);\r
-               exit_code = 1;\r
+         //movedata ((unsigned)screen,7,0xb800,0,7*160);\r
+         //gotoxy (10,4);\r
+               printf("\n");\r
+         puts(error);\r
+               printf("\n");\r
+         //gotoxy (1,8);\r
+         exit(1);\r
        }\r
-#ifndef CATALOG\r
        else\r
-       if (!NoWait)\r
+       if (!error || !(*error))\r
        {\r
-               movedata (finscreen,0,0xb800,0,4000);\r
-               bioskey (0);\r
+               //clrscr();\r
+               //#ifndef JAPAN\r
+               movedata ((unsigned)screen,7,0xb800,0,4000);\r
+               //gotoxy(1,24);\r
+               //#endif\r
+//asm  mov     bh,0\r
+//asm  mov     dh,23   // row\r
+//asm  mov     dl,0    // collumn\r
+//asm  mov ah,2\r
+//asm  int     0x10\r
        }\r
-#endif\r
 \r
-       va_end(ap);\r
+       exit(0);\r
+}\r
 \r
-#ifndef CATALOG\r
-       if (!error)\r
-       {\r
-               _argc = 2;\r
-               _argv[1] = "LAST.SHL";\r
-               _argv[2] = "ENDSCN.SCN";\r
-               _argv[3] = NULL;\r
-               if (execv("LOADSCN.EXE", _argv) == -1)\r
-               {\r
-                       clrscr();\r
-                       puts("Couldn't find executable LOADSCN.EXE.\n");\r
-                       exit(1);\r
-               }\r
-       }\r
+//===========================================================================\r
 #endif\r
 \r
-       exit(exit_code);\r
-}*/\r
-\r
 byte dirchar(byte in)\r
 {\r
        byte out;\r
index 74822da2d4db5b2b87d315b21ad67ac9076e1b20..6b189d875fcd864c0cb1107332c937739a47bd27 100755 (executable)
@@ -28,8 +28,8 @@
 #error i8088 only\r
 #endif\r
 \r
-#ifndef _LIBHEAD_H_\r
-#define _LIBHEAD_H_\r
+#ifndef __16_HEAD_H__\r
+#define __16_HEAD_H__\r
 #include <dos.h>\r
 #include <stdio.h>\r
 #include <stdlib.h>\r
 #include <sys/stat.h>\r
 #include <mem.h>\r
 #include <string.h>\r
+#include <limits.h>\r
+#include <errno.h>\r
+#include <process.h>\r
 #ifdef __WATCOMC__\r
 #include <i86.h>\r
 #include <unistd.h>\r
 #include <alloca.h>\r
 #include <stdint.h> //16_vrs.h\r
 #endif\r
+#ifdef __BORLANDC__\r
+#include <values.h>\r
+#include <dir.h>\r
+#define TILEWH 16\r
+#endif\r
 #include "src/lib/nyan/kitten.h"\r
 #include "src/lib/types.h"\r
 #include "src/lib/typdefst.h"\r
@@ -151,6 +159,8 @@ static word far* clockw= (word far*) 0x046C; /* 18.2hz clock */
 extern int                     profilehandle,debughandle;      //make it into game global\r
 \r
 #define __DEBUG__\r
+//#define __DEBUG_PM__\r
+//#define __DEBUG_MM__\r
 \r
 #define        nil     ((void *)0)\r
 #ifdef __BORLANDC__\r
@@ -159,7 +169,25 @@ extern     int                     profilehandle,debughandle;      //make it into game global
 #endif\r
 #ifdef __WATCOMC__\r
 #define _FCORELEFT 0x90000UL+16UL\r
+static union REGS CPURegs;\r
+\r
+#define _AX CPURegs.x.ax\r
+#define _BX CPURegs.x.bx\r
+#define _CX CPURegs.x.cx\r
+#define _DX CPURegs.x.dx\r
+\r
+#define _SI CPURegs.x.si\r
 \r
+#define _AH CPURegs.h.ah\r
+#define _AL CPURegs.h.al\r
+#define _BH CPURegs.h.bh\r
+#define _BL CPURegs.h.bl\r
+#define _CH CPURegs.h.ch\r
+#define _CL CPURegs.h.cl\r
+#define _DH CPURegs.h.dh\r
+#define _DL CPURegs.h.dl\r
+\r
+#define geninterrupt(n) int86(n,&CPURegs,&CPURegs);\r
 #define peekb(segm,ofs) (*(byte far*)MK_FP((segm),(ofs)))\r
 #define peekw(segm,ofs) (*(word far*)MK_FP((segm),(ofs)))\r
 #define pokeb(segm,ofs,value) (peekb((segm),(ofs)) = (byte)(value))\r
@@ -171,11 +199,12 @@ typedef union REGPACK     regs_t;
 #define INPUT_STATUS_1         0x03da\r
 \r
 /* local function */\r
-void wait(clock_t wait);\r
-\r
 long int filesize(FILE *fp);\r
 void printmeminfoline(byte *strc, const byte *pee, size_t h_total, size_t h_used, size_t h_free);\r
 int US_CheckParm(char *parm,char **strings);\r
+#ifdef __BORLANDC__\r
+void Quit (char *error);\r
+#endif\r
 byte dirchar(byte in);\r
 \r
-#endif/*_LIBHEAD_H_*/\r
+#endif/*__16_HEAD_H__*/\r
index 6df6d06af3927c9243beec8ba9b957b89f8388ed..85709c5e00c53fc90dd649a8698984b3741005ba 100755 (executable)
@@ -38,7 +38,9 @@
 \r
 #include "src/lib/16_in.h"\r
 \r
-boolean testkeyin=0,testcontrolnoisy=0;\r
+#ifdef __DEBUG_InputMgr__\r
+boolean dbg_testkeyin=0,dbg_testcontrolnoisy=0;\r
+#endif\r
 \r
 /*\r
 =============================================================================\r
@@ -164,6 +166,7 @@ static      Direction       DirTable[] =            // Quick lookup for total direction
 #endif\r
 \r
 //     Internal routines\r
+\r
 ///////////////////////////////////////////////////////////////////////////\r
 //\r
 //     INL_KeyService() - Handles a keyboard interrupt (key up/down)\r
@@ -234,18 +237,22 @@ static    boolean special;
 \r
        if (INL_KeyHook && !special)\r
                INL_KeyHook();\r
-//#ifdef TESTKEYIN\r
-       if(testkeyin > 0) printf("%c    %u      [0x%x %u]       %u\n", c, c, k, k, inpu.Keyboard[k]);\r
-//endif\r
+#ifdef __DEBUG_InputMgr__\r
+       if(dbg_testkeyin > 0) printf("%c        %u      [0x%x %u]       %u\n", c, c, k, k, inpu.Keyboard[k]);\r
+#endif\r
        outp(0x20,0x20);\r
 }\r
 \r
 void\r
 Mouse(int x)\r
 {\r
-       union REGS CPURegs;\r
-       x = CPURegs.x.ax;\r
-       int86(MouseInt,&CPURegs,&CPURegs);\r
+       //union REGS CPURegs;\r
+       //x = CPURegs.x.ax;\r
+       __asm {\r
+               mov     ax,x\r
+               int     MouseInt\r
+       }\r
+       //int86(MouseInt,&CPURegs,&CPURegs);\r
 }\r
 \r
 ///////////////////////////////////////////////////////////////////////////\r
@@ -299,8 +306,7 @@ IN_GetJoyAbs(word joy,word *xp,word *yp)
        yb = 1 << ys;\r
 \r
 // Read the absolute joystick values\r
-       __asm\r
-       {\r
+       __asm {\r
                pushf                           // Save some registers\r
                push    si\r
                push    di\r
@@ -320,8 +326,13 @@ IN_GetJoyAbs(word joy,word *xp,word *yp)
 \r
                push    bp                      // Don't mess up stack frame\r
                mov             bp,MaxJoyValue\r
-\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
 loo:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
                in              al,dx           // Get bits indicating whether all are finished\r
 \r
                dec             bp                      // Check bounding register\r
@@ -338,8 +349,13 @@ loo:
 \r
                add             cl,bl\r
                jnz             loo             // If both bits were 0, drop out\r
-\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
 done:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
                pop             bp\r
 \r
                mov             cl,[xs]         // Get the number of bits to shift\r
@@ -637,9 +653,9 @@ IN_Startup()
 \r
        checkjoys = true;\r
        checkmouse = true;\r
-       for (i = 1;i < __argc;i++)\r
+       for (i = 1;i < _argc;i++)\r
        {\r
-               switch (US_CheckParm(__argv[i],ParmStringsIN))\r
+               switch (US_CheckParm(_argv[i],ParmStringsIN))\r
                {\r
                case 0:\r
                        checkjoys = false;\r
@@ -881,7 +897,9 @@ register    KeyboardDef     *def;
                                                default:\r
                                                break;\r
                                        }\r
-                                       //if(testcontrolnoisy > 0){ printf("dir=%c ", dirchar(dir)); printf("pdir=%c    ", dirchar(player[pn].pdir)); }\r
+#ifdef __DEBUG_InputMgr__\r
+                                       //if(dbg_testcontrolnoisy > 0){ printf("dir=%c ", dirchar(dir)); printf("pdir=%c        ", dirchar(player[pn].pdir)); }\r
+#endif\r
                                }\r
                        }\r
                        //input from player\r
@@ -962,7 +980,8 @@ register    KeyboardDef     *def;
                }\r
        }\r
 #endif\r
-if(testcontrolnoisy > 0)\r
+#ifdef __DEBUG_InputMgr__\r
+if(dbg_testcontrolnoisy > 0)\r
 if(player[pn].info.dir!=2/*(inpu.Keyboard[def->up] || inpu.Keyboard[def->down] || inpu.Keyboard[def->left] || inpu.Keyboard[def->right])*/ || player[pn].q>1)\r
 {\r
        //printf("b1=%u b2=%u b3=%u b4=%u       ", player[pn].info.button0, player[pn].info.button1, player[pn].info.button2, player[pn].info.button3);\r
@@ -973,6 +992,7 @@ if(player[pn].info.dir!=2/*(inpu.Keyboard[def->up] || inpu.Keyboard[def->down] |
        //else if(!realdelta) printf("%c%d %c%d %c%d %c%d", dirchar(0), inpu.Keyboard[def->up], dirchar(4), inpu.Keyboard[def->down], dirchar(1), inpu.Keyboard[def->left], dirchar(3), inpu.Keyboard[def->right]);\r
        printf("\n");\r
 }\r
+#endif\r
 }\r
 \r
 ///////////////////////////////////////////////////////////////////////////\r
@@ -1155,6 +1175,9 @@ IN_Ack()
 {\r
        word    i;\r
 \r
+       if (!inst.IN_Started)\r
+               return;\r
+\r
        IN_ClearKey(inpu.LastScan);\r
        inpu.LastScan = sc_None;\r
 \r
@@ -1236,9 +1259,9 @@ void IN_ClearKey(byte code)
 \r
 boolean IN_qb(byte kee)\r
 {\r
-//#ifdef TESTKEYIN\r
-//     if(testkeyin > 0) printf("%u\n", inpu.Keyboard[kee]);\r
-//#endif\r
+#ifdef __DEBUG_InputMgr__\r
+//     if(dbg_testkeyin > 0) printf("%u\n", inpu.Keyboard[kee]);\r
+#endif\r
        if(inpu.Keyboard[kee]==true) return 1;\r
        else return 0;\r
 }\r
index 16b9b0aeab16accbd8f778ae988c97c34dec478e..29ecc130e1f91616bf870bd9f88a895c6ea30f90 100755 (executable)
 #include "src/lib/bitmap.h"    //old format\r
 #endif\r
 #ifdef __DEBUG__\r
-//#define      __DEBUG_InputMgr__\r
+#define        __DEBUG_InputMgr__\r
+extern boolean dbg_testkeyin,dbg_testcontrolnoisy;\r
 #endif\r
 \r
-#ifdef __DEBUG_InputMgr__\r
-//#define TESTKEYIN\r
-//#define TESTCONTROLNOISY\r
-#endif\r
-\r
-extern boolean testkeyin,testcontrolnoisy;\r
-\r
 //if else for gfxtesting and direction\r
 //player[pn].d == 2 ||\r
 //player[pn].d != 2 ||\r
@@ -231,7 +225,10 @@ typedef    struct
 //0000 planar_buf_t huge *data; //supposively the sprite sheet data\r
 //     planar_buf_t data; //supposively the sprite sheet data\r
 ////0000----\r
-       struct sprite *spri;    //supposively the sprite sheet data\r
+#ifdef __WATCOMC__\r
+       struct sprite   *spri;  //supposively the sprite sheet data\r
+       memptr          gr;\r
+#endif\r
        bitmap_t *data;         //supposively the sprite sheet data//old format\r
        sword hp; //hitpoints of the player\r
        int persist_aniframe;    /* gonna be increased to 1 before being used, so 0 is ok for default */\r
index 8e2d65b2de75763aabe807e57fd894b08e699be2..d697142d34a940f639141a717857513451fb60b9 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "16_map.h"
-
-// Ideally, preprocess json during compilation and read serialized data
-
-int jsoneq(const char *json, jsmntok_t *tok, const char *s) {
-       if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
-                       strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
-               return 0;
-       }
-       return -1;
-}
-
-void extract_map(const char *js, jsmntok_t *t, size_t count, map_t *map) {
-       int i, j, k, indent, inner_end;
-       bitmap_t bp;
-       char *s;
-       i = 0;
-       while(i<count) {
-               if(jsoneq(js, &(t[i]), "layers") == 0) {
-                       i++;
-                       map->data = malloc(sizeof(byte*) * t[i].size);
-                       inner_end = t[i].end;
-                       k = 0;
-                       while(t[i].start < inner_end) {
-                               printf("%d, %d\n", t[i].start, inner_end);
-                               if(jsoneq(js, &(t[i]), "data") == 0) {
-                                       #ifdef DEBUG_MAPVAR
-                                       printf("Layer %d data: [", k);
-                                       #endif
-                                       map->data[k] = malloc(sizeof(byte) * t[i+1].size);
-                                       for(j = 0; j < t[i+1].size; j++) {
-                                               map->data[k][j] = (byte)atoi(js + t[i+2+j].start);
-                                               #ifdef DEBUG_MAPVAR
-                                               printf("%d, ", map->data[k][j]);
-                                               #endif
-                                       }
-                                       i += j + 2;
-                                       k++;
-                                       #ifdef DEBUG_MAPVAR
-                                       puts("]");
-                                       #endif
-                               }
-                               else{
-                                       i++;
-                               }
-                       }
-               }
-               if(jsoneq(js, &(t[i]), "tilesets") == 0) {
-                       i++;
-                       map->tiles = malloc(sizeof(tiles_t*) * t[i].size);
-                       inner_end = t[i].end;
-                       k = 0;
-                       while(t[i].start < inner_end) {
-                               if(jsoneq(js, &(t[i]), "image") == 0) {
-                                       //fix this to be far~
-                                       map->tiles[k] = malloc(sizeof(tiles_t));
-                                       map->tiles[k]->btdata = malloc(sizeof(bitmap_t));
-                                       map->tiles[k]->tileHeight = 16;
-                                       map->tiles[k]->tileWidth = 16;
-                                       map->tiles[k]->rows = 1;
-                                       map->tiles[k]->cols = 1;
-                                       map->tiles[k]->debug_text=false;
-                                       //Fix to load tileset specified.
-                                       //And move to vrs, probably
-                                       bp = bitmapLoadPcx("data/ed.pcx");
-                                       map->tiles[k]->btdata = &bp;
-                                       k++;
-                               }
-                               i++;
-                       }
-               }
-
-               if (jsoneq(js, &(t[i]), "height") == 0 && indent<=1) {
-                       map->height = atoi(js + t[i+1].start);
-                       #ifdef DEBUG_MAPVAR
-                       printf("Height: %d\n", map->height);
-                       #endif
-                       i++;
-               }
-               else if(jsoneq(js, &(t[i]), "width") == 0 && indent<=1) {
-                       map->width = atoi(js + t[i+1].start);
-                       #ifdef DEBUG_MAPVAR
-                       printf("Width: %d\n", map->width);
-                       #endif
-                       i++;
-               }
-               i++;
-       }
-}
-
-int loadmap(char *mn, map_t *map) {
-       char *js;
-
-       jsmn_parser p;
-       jsmntok_t *tok = NULL;
-       size_t tokcount, file_s;
-
-       FILE *fh = fopen(mn, "r");
-       int status;
-
-       /* Prepare parser */
-       jsmn_init(&p);
-
-       file_s = filesize(fh);
-       js = malloc(file_s);
-       if(js == NULL) {
-               fprintf(stderr, "malloc(): errno = %d", 2);
-               fclose(fh);
-               return 3;
-       }
-       if(fread(js, 1, file_s, fh) != file_s) {
-               fprintf(stderr, "Map read error");
-               free(js);
-               fclose(fh);
-               return 1;
-       }
-       tokcount = jsmn_parse(&p, js, file_s, NULL, 0);
-       tok = malloc(tokcount*sizeof(jsmntok_t));
-       printf("Allocated %d tokens", tokcount);
-       jsmn_init(&p);
-       if((status = jsmn_parse(&p, js, file_s, tok, tokcount)) < 0)
-       {
-               printf("Error: %d\n", status);
-               return status;
-       }
-       else if(status != tokcount) { printf("Warning: used %d tok\n", status);}
-       extract_map(js, tok, tokcount, map);
-
-       free(js);
-       free(tok);
-       fclose(fh);
-       
-       return 0;
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "16_map.h"\r
+\r
+// Ideally, preprocess json during compilation and read serialized data\r
+\r
+int jsoneq(const char *json, jsmntok_t *tok, const char *s) {\r
+       if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&\r
+                       strncmp(json + tok->start, s, tok->end - tok->start) == 0) {\r
+               return 0;\r
+       }\r
+       return -1;\r
+}\r
+\r
+void extract_map(const char *js, jsmntok_t *t, size_t count, map_t *map) {\r
+       int i, j, k, indent, inner_end;\r
+       bitmap_t bp;\r
+       char *s;\r
+       i = 0;\r
+       while(i<count) {\r
+               if(jsoneq(js, &(t[i]), "layers") == 0) {\r
+                       i++;\r
+                       map->data = malloc(sizeof(byte*) * t[i].size);\r
+                       inner_end = t[i].end;\r
+                       k = 0;\r
+                       while(t[i].start < inner_end) {\r
+                               printf("%d, %d\n", t[i].start, inner_end);\r
+                               if(jsoneq(js, &(t[i]), "data") == 0) {\r
+                                       #ifdef DEBUG_MAPVAR\r
+                                       printf("Layer %d data: [", k);\r
+                                       #endif\r
+                                       map->data[k] = malloc(sizeof(byte) * t[i+1].size);\r
+                                       for(j = 0; j < t[i+1].size; j++) {\r
+                                               map->data[k][j] = (byte)atoi(js + t[i+2+j].start);\r
+                                               #ifdef DEBUG_MAPVAR\r
+                                               printf("%d, ", map->data[k][j]);\r
+                                               #endif\r
+                                       }\r
+                                       i += j + 2;\r
+                                       k++;\r
+                                       #ifdef DEBUG_MAPVAR\r
+                                       puts("]");\r
+                                       #endif\r
+                               }\r
+                               else{\r
+                                       i++;\r
+                               }\r
+                       }\r
+               }\r
+               if(jsoneq(js, &(t[i]), "tilesets") == 0) {\r
+                       i++;\r
+                       map->tiles = malloc(sizeof(tiles_t*) * t[i].size);\r
+                       inner_end = t[i].end;\r
+                       k = 0;\r
+                       while(t[i].start < inner_end) {\r
+                               if(jsoneq(js, &(t[i]), "image") == 0) {\r
+                                       //fix this to be far~\r
+                                       map->tiles[k] = malloc(sizeof(tiles_t));\r
+                                       map->tiles[k]->btdata = malloc(sizeof(bitmap_t));\r
+                                       map->tiles[k]->tileHeight = 16;\r
+                                       map->tiles[k]->tileWidth = 16;\r
+                                       map->tiles[k]->rows = 1;\r
+                                       map->tiles[k]->cols = 1;\r
+                                       map->tiles[k]->debug_text=false;\r
+                                       //Fix to load tileset specified.\r
+                                       //And move to vrs, probably\r
+                                       bp = bitmapLoadPcx("data/ed.pcx");\r
+                                       map->tiles[k]->btdata = &bp;\r
+                                       k++;\r
+                               }\r
+                               i++;\r
+                       }\r
+               }\r
+\r
+               if (jsoneq(js, &(t[i]), "height") == 0 && indent<=1) {\r
+                       map->height = atoi(js + t[i+1].start);\r
+                       #ifdef DEBUG_MAPVAR\r
+                       printf("Height: %d\n", map->height);\r
+                       #endif\r
+                       i++;\r
+               }\r
+               else if(jsoneq(js, &(t[i]), "width") == 0 && indent<=1) {\r
+                       map->width = atoi(js + t[i+1].start);\r
+                       #ifdef DEBUG_MAPVAR\r
+                       printf("Width: %d\n", map->width);\r
+                       #endif\r
+                       i++;\r
+               }\r
+               i++;\r
+       }\r
+}\r
+\r
+int loadmap(char *mn, map_t *map) {\r
+       char *js;\r
+\r
+       jsmn_parser p;\r
+       jsmntok_t *tok = NULL;\r
+       size_t tokcount, file_s;\r
+\r
+       FILE *fh = fopen(mn, "r");\r
+       int status;\r
+\r
+       /* Prepare parser */\r
+       jsmn_init(&p);\r
+\r
+       file_s = filesize(fh);\r
+       js = malloc(file_s);\r
+       if(js == NULL) {\r
+               fprintf(stderr, "malloc(): errno = %d", 2);\r
+               fclose(fh);\r
+               return 3;\r
+       }\r
+       if(fread(js, 1, file_s, fh) != file_s) {\r
+               fprintf(stderr, "Map read error");\r
+               free(js);\r
+               fclose(fh);\r
+               return 1;\r
+       }\r
+       tokcount = jsmn_parse(&p, js, file_s, NULL, 0);\r
+       tok = malloc(tokcount*sizeof(jsmntok_t));\r
+       printf("Allocated %d tokens", tokcount);\r
+       jsmn_init(&p);\r
+       if((status = jsmn_parse(&p, js, file_s, tok, tokcount)) < 0)\r
+       {\r
+               printf("Error: %d\n", status);\r
+               return status;\r
+       }\r
+       else if(status != tokcount) { printf("Warning: used %d tok\n", status);}\r
+       extract_map(js, tok, tokcount, map);\r
+\r
+       free(js);\r
+       free(tok);\r
+       fclose(fh);\r
+       \r
+       return 0;\r
+}\r
index add7707e00435baa7ec00aeff435932b5a90ef57..42a87440485b974a3b11baf23fb91f8c5119db73 100755 (executable)
@@ -140,7 +140,7 @@ boolean MML_CheckForEMS(void)
        return(emmcfems);
 }
 
-
+#ifndef __16_PM__
 /*
 ======================
 =
@@ -149,7 +149,7 @@ boolean MML_CheckForEMS(void)
 =======================
 */
 
-byte MML_SetupEMS(mminfo_t *mm)
+byte MML_SetupEMS(global_game_variables_t *gvar)
 {
        byte    str[160];
        byte    err;
@@ -157,8 +157,8 @@ byte MML_SetupEMS(mminfo_t *mm)
 
        unsigned int EMSVer = 0;
        //byte  EMS_status;
-       unsigned        totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;
-       totalEMSpages = freeEMSpages = EMSpageframe = EMSpagesmapped = 0;
+       unsigned        totalEMSpages,freeEMSpages,EMSPageFrame,EMSpagesmapped,EMSHandle;
+       totalEMSpages = freeEMSpages = EMSPageFrame = EMSpagesmapped = 0;
 
        __asm {
                mov     ah,EMS_STATUS
@@ -179,7 +179,7 @@ byte MML_SetupEMS(mminfo_t *mm)
                int     EMS_INT                                         // find the page frame address
                or      ah,ah
                jnz     error
-               mov     [EMSpageframe],bx
+               mov     [EMSPageFrame],bx
 
                mov     ah,EMS_GETPAGES
                int     EMS_INT                                         // find out how much EMS is there
@@ -218,7 +218,7 @@ byte MML_SetupEMS(mminfo_t *mm)
                int     EMS_INT
                or      ah,ah
                jnz     error
-               mov     [EMShandle],dx
+               mov     [EMSHandle],dx
                jmp End
 #ifdef __BORLANDC__
        }
@@ -245,12 +245,12 @@ End:
                printf("%s\n",str);
                return err;
        }
-       mm->totalEMSpages=totalEMSpages;
-       mm->freeEMSpages=freeEMSpages;
-       mm->EMSpageframe=EMSpageframe;
-       mm->EMSpagesmapped=EMSpagesmapped;
-       mm->EMShandle=EMShandle;
-       mm->EMSVer=EMSVer;
+       gvar->mm.totalEMSpages=totalEMSpages;
+       gvar->mm.freeEMSpages=freeEMSpages;
+       gvar->mm.EMSPageFrame=EMSPageFrame;
+       gvar->mm.EMSpagesmapped=EMSpagesmapped;
+       gvar->mm.EMSHandle=EMSHandle;
+       gvar->mm.EMSVer=EMSVer;
        return 0;
 }
 
@@ -263,16 +263,16 @@ End:
 =======================
 */
 
-void MML_ShutdownEMS(mminfo_t *mm)
+void MML_ShutdownEMS(global_game_variables_t *gvar)
 {
        boolean errorflag=false;
-       unsigned EMShandle=mm->EMShandle;
+       unsigned EMSHandle=gvar->mm.EMSHandle;
 
-       if(!EMShandle)
+       if(!EMSHandle)
                return;
        __asm {
                mov     ah,EMS_FREEPAGES
-               mov     dx,[EMShandle]
+               mov     dx,[EMSHandle]
                int     EMS_INT
                or      ah,ah
                jz      ok
@@ -284,7 +284,8 @@ void MML_ShutdownEMS(mminfo_t *mm)
 #ifdef __WATCOMC__
        }
 #endif
-       if(errorflag==true) printf("MML_ShutdownEMS: Error freeing EMS!\n");    //++++ add something
+       if(errorflag==true)
+               Quit("MML_ShutdownEMS: Error freeing EMS!\n");  //++++ add something
 }
 
 /*
@@ -299,14 +300,14 @@ void MML_ShutdownEMS(mminfo_t *mm)
 ====================
 */
 
-byte MM_MapEMS(mminfo_t *mm, mminfotype *mmi)
+byte MM_MapEMS(global_game_variables_t *gvar)
 {
        byte    str[160];
-       unsigned        EMShandle;
+       unsigned        EMSHandle;
        byte err;
        boolean errorflag=false;
        int     i;
-       EMShandle=mm->EMShandle;
+       EMSHandle=gvar->mm.EMSHandle;
 
        for (i=0;i<4/*MAPPAGES*/;i++)
        {
@@ -314,7 +315,7 @@ byte MM_MapEMS(mminfo_t *mm, mminfotype *mmi)
                        mov     ah,EMS_MAPPAGE
                        mov     bx,[i]                  // logical page
                        mov     al,bl                   // physical page
-                       mov     dx,[EMShandle]  // handle
+                       mov     dx,[EMSHandle]  // handle
                        int     EMS_INT
                        or      ah,ah
                        jnz     error
@@ -343,12 +344,11 @@ byte MM_MapEMS(mminfo_t *mm, mminfotype *mmi)
                        return err;
                }
        }
-       mmi->EMSmem = (i)*0x4000lu;
-       //printf("              mmi->EMSmem=%lu\n", mmi->EMSmem);
+       gvar->mmi.EMSmem = (i)*0x4000lu;
        return 0;
 }
 
-byte MM_MapXEMS(mminfo_t *mm, mminfotype *mmi)
+byte MM_MapXEMS(global_game_variables_t *gvar)
 {
 //SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)
 
@@ -374,12 +374,12 @@ byte MM_MapXEMS(mminfo_t *mm, mminfotype *mmi)
 //END SUB
        byte    str[160];
        byte err;
-       word    EMShandle;
+       word    EMSHandle;
        boolean errorflag=false;
        int     i;
-       EMShandle=mm->EMShandle;
+       EMSHandle=gvar->mm.EMSHandle;
 
-       if(mm->EMSVer<0x40)
+       if(gvar->mm.EMSVer<0x40)
                return 5;
 
        for (i=0;i<MAPPAGES;i++)
@@ -388,7 +388,7 @@ byte MM_MapXEMS(mminfo_t *mm, mminfotype *mmi)
                        mov     ah,EMS_MAPXPAGE
                        mov     cx,[i]                  // logical page
                        mov     al,bl                   // physical page
-                       mov     dx,[EMShandle]  // handle
+                       mov     dx,[EMSHandle]  // handle
                        int     EMS_INT
                        or      ah,ah
                        jnz     error
@@ -421,10 +421,10 @@ byte MM_MapXEMS(mminfo_t *mm, mminfotype *mmi)
                        return err;
                }
        }
-       mmi->EMSmem = (i)*0x4000lu;
+       gvar->mmi.EMSmem = (i)*0x4000lu;
        return 0;
 }
-
+#endif
 //==========================================================================
 
 /*
@@ -437,10 +437,10 @@ byte MM_MapXEMS(mminfo_t *mm, mminfotype *mmi)
 =======================
 */
 
-boolean MML_CheckForXMS(mminfo_t *mm)
+boolean MML_CheckForXMS(void)
 {
+       //numUMBs = 0;
        boolean errorflag=false;
-       mm->numUMBs = 0;
 
        __asm {
                mov     ax,0x4300
@@ -459,7 +459,7 @@ boolean MML_CheckForXMS(mminfo_t *mm)
        else return true;
 }
 
-
+#ifndef __16_PM__
 /*
 ======================
 =
@@ -470,7 +470,7 @@ boolean MML_CheckForXMS(mminfo_t *mm)
 =======================
 */
 
-void MML_SetupXMS(mminfo_t *mm, mminfotype *mmi)
+void MML_SetupXMS(global_game_variables_t *gvar)
 {
        word    base,size;
 
@@ -514,11 +514,11 @@ getmemory:
        }
 #endif
 //     printf("base=%u ", base); printf("size=%u\n", size);
-       MML_UseSpace(base,size, mm);
-       mmi->XMSmem += size*16;
-       mm->UMBbase[mm->numUMBs] = base;
-       mm->numUMBs++;
-       if(mm->numUMBs < MAXUMBS)
+       MML_UseSpace(base,size, gvar);
+       gvar->mmi.XMSmem += size*16;
+       gvar->mm.UMBbase[gvar->mm.numUMBs] = base;
+       gvar->mm.numUMBs++;
+       if(gvar->mm.numUMBs < MAXUMBS)
                goto getmemory;
 }
 
@@ -531,14 +531,14 @@ getmemory:
 ======================
 */
 
-void MML_ShutdownXMS(mminfo_t *mm)
+void MML_ShutdownXMS(global_game_variables_t *gvar)
 {
        int     i;
        unsigned        base;
 
-       for (i=0;i<mm->numUMBs;i++)
+       for (i=0;i<gvar->mm.numUMBs;i++)
        {
-               base = mm->UMBbase[i];
+               base = gvar->mm.UMBbase[i];
                __asm {
                        mov     ah,XMS_FREEUMB
                        mov     dx,[base]
@@ -546,7 +546,7 @@ void MML_ShutdownXMS(mminfo_t *mm)
                }
        }
 }
-
+#endif
 //==========================================================================
 
 /*
@@ -561,7 +561,7 @@ void MML_ShutdownXMS(mminfo_t *mm)
 ======================
 */
 
-/*void MML_UseSpace(word segstart, dword seglength, mminfo_t *mm)
+/*void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)
 {
        //huge mmblocktype huge *scan,huge *last;
        word            segm=1;
@@ -569,8 +569,8 @@ void MML_ShutdownXMS(mminfo_t *mm)
        dword           segmlen;
        dword           extra;
 
-       scan = last = mm->mmhead;
-       mm->mmrover = mm->mmhead;               // reset rover to start of memory
+       scan = last = gvar->mm.mmhead;
+       gvar->mm.mmrover = gvar->mm.mmhead;             // reset rover to start of memory
 
 //
 // search for the block that contains the range of segments
@@ -595,7 +595,7 @@ void MML_ShutdownXMS(mminfo_t *mm)
        {
                scan->blob=segm;
 
-               //MML_UseSpace(segstart, seglength, mm);
+               //MML_UseSpace(segstart, seglength, gvar);
 
                printf("MML_UseSpace: Segment spans two blocks!\n");
        //}
@@ -621,25 +621,25 @@ void MML_ShutdownXMS(mminfo_t *mm)
        if(extra > 0)
        {
                GETNEWBLOCK;
-               mm->mmnew->useptr = NULL;
+               gvar->mm.mmnew->useptr = NULL;
 
-               mm->mmnew->next = scan->next;
-               scan->next = mm->mmnew;
-               mm->mmnew->start = segstart+seglength;
-               mm->mmnew->length = extra;
-               mm->mmnew->attributes = LOCKBIT;
+               gvar->mm.mmnew->next = scan->next;
+               scan->next = gvar->mm.mmnew;
+               gvar->mm.mmnew->start = segstart+seglength;
+               gvar->mm.mmnew->length = extra;
+               gvar->mm.mmnew->attributes = LOCKBIT;
        }//else if(segm>0) goto segu;
 
 }*/
-void MML_UseSpace(word segstart, dword seglength, mminfo_t *mm)
+void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)
 {
        mmblocktype far *scan,far *last;
        word    oldend;
        sdword          extra;
        //word segm=1;
 
-       scan = last = mm->mmhead;
-       mm->mmrover = mm->mmhead;               // reset rover to start of memory
+       scan = last = gvar->mm.mmhead;
+       gvar->mm.mmrover = gvar->mm.mmhead;             // reset rover to start of memory
 
 //
 // search for the block that contains the range of segments
@@ -691,13 +691,13 @@ void MML_UseSpace(word segstart, dword seglength, mminfo_t *mm)
        if (extra > 0)
        {
                GETNEWBLOCK;
-               mm->mmnew->useptr = NULL;
+               gvar->mm.mmnew->useptr = NULL;
 
-               mm->mmnew->next = scan->next;
-               scan->next = mm->mmnew;
-               mm->mmnew->start = segstart+seglength;
-               mm->mmnew->length = extra;
-               mm->mmnew->attributes = LOCKBIT;
+               gvar->mm.mmnew->next = scan->next;
+               scan->next = gvar->mm.mmnew;
+               gvar->mm.mmnew->start = segstart+seglength;
+               gvar->mm.mmnew->length = extra;
+               gvar->mm.mmnew->attributes = LOCKBIT;
        }
 
 }
@@ -714,18 +714,18 @@ void MML_UseSpace(word segstart, dword seglength, mminfo_t *mm)
 ====================
 */
 
-void MML_ClearBlock(mminfo_t *mm)
+void MML_ClearBlock(global_game_variables_t *gvar)
 {
        //huge mmblocktype huge *scan,huge *last;
        mmblocktype far *scan,far *last;
 
-       scan = mm->mmhead->next;
+       scan = gvar->mm.mmhead->next;
 
        while(scan)
        {
                if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS))
                {
-                       MM_FreePtr(scan->useptr, mm);
+                       MM_FreePtr(scan->useptr, gvar);
                        return;
                }
                scan = scan->next;
@@ -748,7 +748,7 @@ void MML_ClearBlock(mminfo_t *mm)
 ===================
 */
 
-void MM_Startup(mminfo_t *mm, mminfotype *mmi)
+void MM_Startup(global_game_variables_t *gvar)
 {
        int i;
        //dword length,seglength;
@@ -758,34 +758,34 @@ void MM_Startup(mminfo_t *mm, mminfotype *mmi)
        word    segstart;//,endfree;
        //memptr *peeonself;
 
-//     if(mm->mmstarted)
-//             MM_Shutdown(mm);
+       if(gvar->mm.mmstarted)
+               MM_Shutdown(gvar);
 
-       mm->mmstarted = true;
-       mm->bombonerror = true;
+       gvar->mm.mmstarted = true;
+       gvar->mm.bombonerror = true;
 
 //
 // set up the linked list (everything in the free list;
 //
-       mm->mmhead = NULL;
-       mm->mmfree = &(mm->mmblocks[0]);
+       gvar->mm.mmhead = NULL;
+       gvar->mm.mmfree = &(gvar->mm.mmblocks[0]);
        for(i=0;i<MAXBLOCKS-1;i++)
        {
-               mm->mmblocks[i].next = &(mm->mmblocks[i+1]);
+               gvar->mm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]);
        }
-       mm->mmblocks[i].next = NULL;
+       gvar->mm.mmblocks[i].next = NULL;
 
 //
 // locked block of all memory until we punch out free space
 //
        GETNEWBLOCK;
-       mm->mmhead = mm->mmnew;                         // this will allways be the first node
-       mm->mmnew->start = 0;
-       mm->mmnew->length = 0xffff;
-       mm->mmnew->attributes = LOCKBIT;
-       mm->mmnew->next = NULL;
-       //mm->mmnew->useptr = peeonself;
-       mm->mmrover = mm->mmhead;
+       gvar->mm.mmhead = gvar->mm.mmnew;                               // this will allways be the first node
+       gvar->mm.mmnew->start = 0;
+       gvar->mm.mmnew->length = 0xffff;
+       gvar->mm.mmnew->attributes = LOCKBIT;
+       gvar->mm.mmnew->next = NULL;
+       //gvar->mm.mmnew->useptr = peeonself;
+       gvar->mm.mmrover = gvar->mm.mmhead;
 
        //printf("              %x\n", peeonself);
        //printf("              %x\n", *peeonself);
@@ -795,20 +795,20 @@ void MM_Startup(mminfo_t *mm, mminfotype *mmi)
 #ifdef __WATCOMC__
        _nheapgrow();
        length=(dword)_memavl();//(dword)GetFreeSize();
-       //huge start = (void huge *)(mm->nearheap = _nmalloc(length));
-       start = (void far *)(mm->nearheap = _nmalloc(length));
+       //huge start = (void huge *)(gvar->mm.nearheap = _nmalloc(length));
+       start = (void far *)(gvar->mm.nearheap = _nmalloc(length));
 #endif
 #ifdef __BORLANDC__
        length=coreleft();
-       //huge start = (void huge *)(mm->nearheap = malloc(length));
-       start = (void far *)(mm->nearheap = malloc(length));
+       //huge start = (void huge *)(gvar->mm.nearheap = malloc(length));
+       start = (void far *)(gvar->mm.nearheap = malloc(length));
 #endif
        length -= 16-(FP_OFF(start)&15);
        length -= SAVENEARHEAP;
        seglength = length / 16;                        // now in paragraphs
        segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;
-       MML_UseSpace(segstart,seglength, mm);
-       mmi->nearheap = length;
+       MML_UseSpace(segstart,seglength, gvar);
+       gvar->mmi.nearheap = length;
        //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);
 
 //
@@ -817,96 +817,73 @@ void MM_Startup(mminfo_t *mm, mminfotype *mmi)
        //printf("_FARCORELEFT                          %lu\n", _FCORELEFT);
 #ifdef __WATCOMC__
        _fheapgrow();
+       length=_FCORELEFT;//_fcoreleft();//(dword)GetFarFreeSize();//0xffffUL*4UL;
 #endif
 #ifdef __BORLANDC__
        printf("farcoreleft()                           %lu\n", farcoreleft());
        printf("(farcoreleft()+32)-_FCORELEFT   %d\n", (sword)((farcoreleft()+32)-_FCORELEFT));
+       length=farcoreleft();//_fcoreleft();//(dword)GetFarFreeSize();//0xffffUL*4UL;
 #endif
-       length=_FCORELEFT;//_fcoreleft();//(dword)GetFarFreeSize();//0xffffUL*4UL;
-       start = mm->farheap = _fmalloc(length);
-       //start = mm->farheap = halloc(length, 1);
+       start = gvar->mm.farheap = _fmalloc(length);
+       //start = gvar->mm.farheap = halloc(length, 1);
        length -= 16-(FP_OFF(start)&15);
        length -= SAVEFARHEAP;
        seglength = length / 16;                        // now in paragraphs
        segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;
-       MML_UseSpace(segstart,seglength, mm);
-       mmi->farheap = length;
+       MML_UseSpace(segstart,seglength, gvar);
+       gvar->mmi.farheap = length;
        //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);
 
-       mmi->mainmem = mmi->nearheap + mmi->farheap;
+       gvar->mmi.mainmem = gvar->mmi.nearheap + gvar->mmi.farheap;
 
+#ifndef __16_PM__
+       if(!dbg_debugpm) {
 //
 // detect EMS and allocate up to 64K at page frame
 //
-       mmi->EMSmem = 0;
+       gvar->mmi.EMSmem = 0;
 //goto emsskip;        //0000
-       for(i = 1;i <
-#ifdef __WATCOMC__
-       __argc
-#endif
-#ifdef __BORLANDC__
-       _argc
-#endif
-       ;i++)
+       for(i = 1;i < _argc;i++)
        {
-               if(US_CheckParm(
-#ifdef __WATCOMC__
-       __argv[i]
-#endif
-#ifdef __BORLANDC__
-       _argv[i]
-#endif
-                       ,ParmStringsexmm) == 0)
+               if(US_CheckParm(_argv[i],ParmStringsexmm) == 0)
                        goto emsskip;                           // param NOEMS
        }
        if(MML_CheckForEMS())
        {
-               MML_SetupEMS(mm);                                       // allocate space
-               //TODO: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT!
-               MML_UseSpace(mm->EMSpageframe,(MAPPAGES)*0x4000lu, mm);
-               //if(mm->EMSVer<0x40)
-                       MM_MapEMS(mm, mmi);                                     // map in used pages
+               MML_SetupEMS(gvar);                                     // allocate space
+               //16_PM: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT!
+               MML_UseSpace(gvar->mm.EMSPageFrame,(MAPPAGES)*0x4000lu, gvar);
+               //if(gvar->pm.emm.EMSVer<0x40)
+                       MM_MapEMS(gvar);                                        // map in used pages
                //else
-                       //MM_MapXEMS(mm, mmi);                                  // map in used pages
+                       //MM_MapXEMS(gvar);                                     // map in used pages
        }
 
 //
 // detect XMS and get upper memory blocks
 //
 emsskip:
-       mmi->XMSmem = 0;
+       gvar->mmi.XMSmem = 0;
 goto xmsskip;//0000
-       for(i = 1;i <
-#ifdef __WATCOMC__
-       __argc
-#endif
-#ifdef __BORLANDC__
-       _argc
-#endif
-       ;i++)
+       for(i = 1;i < _argc;i++)
        {
-               if(US_CheckParm(
-#ifdef __WATCOMC__
-       __argv[i]
-#endif
-#ifdef __BORLANDC__
-       _argv[i]
-#endif
-                       ,ParmStringsexmm) == 0)
+               if(US_CheckParm( _argv[i],ParmStringsexmm) == 0)
                        goto xmsskip;                           // param NOXMS
        }
-       if(MML_CheckForXMS(mm))
+       if(MML_CheckForXMS())
        {
-               MML_SetupXMS(mm, mmi);                                  // allocate as many UMBs as possible
+               MML_SetupXMS(gvar);                                     // allocate as many UMBs as possible
        }
 
+       }
+xmsskip:
+#endif
 //
 // allocate the misc buffer
 //
-xmsskip:
-       mm->mmrover = mm->mmhead;               // start looking for space after low block
+       gvar->mm.mmrover = gvar->mm.mmhead;             // start looking for space after low block
 
-       MM_GetPtr(&(mm->bufferseg),BUFFERSIZE, mm, mmi);
+       MM_GetPtr(&(gvar->mm.bufferseg),BUFFERSIZE, gvar);
 }
 
 //==========================================================================
@@ -921,20 +898,28 @@ xmsskip:
 ====================
 */
 
-void MM_Shutdown(mminfo_t *mm)
+void MM_Shutdown(global_game_variables_t *gvar)
 {
-       if(!(mm->mmstarted))
+       if(!(gvar->mm.mmstarted))
                return;
 
-       _ffree(mm->farheap);//  printf("                far freed\n");
+       _ffree(gvar->mm.farheap);//     printf("                far freed\n");
 #ifdef __WATCOMC__
-       _nfree(mm->nearheap);// printf("                near freed\n");
+       _nfree(gvar->mm.nearheap);//    printf("                near freed\n");
 #endif
 #ifdef __BORLANDC__
-       free(mm->nearheap);//   printf("                near freed\n");
+       free(gvar->mm.nearheap);//      printf("                near freed\n");
+#endif
+#ifndef __16_PM__
+#ifdef __DEBUG__
+       if(!dbg_debugpm) {
+#endif
+       if(MML_CheckForEMS()){ MML_ShutdownEMS(gvar); }//printf("               EMS freed\n"); }
+       if(MML_CheckForXMS()){ MML_ShutdownXMS(gvar); }//printf("               XMS freed\n"); }
+#ifdef __DEBUG__
+       }
+#endif
 #endif
-       if(MML_CheckForEMS()){ MML_ShutdownEMS(mm); }//printf("         EMS freed\n"); }
-       if(MML_CheckForXMS(mm)){ MML_ShutdownXMS(mm); }//printf("               XMS freed\n"); }
 }
 
 //==========================================================================
@@ -949,7 +934,7 @@ void MM_Shutdown(mminfo_t *mm)
 ====================
 */
 
-void MM_GetPtr (memptr *baseptr, dword size, mminfo_t *mm, mminfotype *mmi)
+void MM_GetPtr (memptr *baseptr, dword size, global_game_variables_t *gvar)
 {
        //huge mmblocktype huge *scan,huge *lastscan,huge *endscan,huge *purge,huge *next;
        mmblocktype far *scan,far *lastscan,far *endscan,far *purge,far *next;
@@ -959,16 +944,18 @@ void MM_GetPtr (memptr *baseptr, dword size, mminfo_t *mm, mminfotype *mmi)
        needed = (size+15)/16;          // convert size from bytes to paragraphs
 
        GETNEWBLOCK;                            // fill in start and next after a spot is found
-       mm->mmnew->length = needed;
-       mm->mmnew->useptr = baseptr;
-       //if(mm->mmnew->useptr==NULL){
-#ifdef __DEBUG__
-               printf("baseptr=%04x    ", baseptr); printf("useptr=%04x\n", mm->mmnew->useptr);
-               printf("*baseptr=%04x   ", *baseptr); printf("*useptr=%04x\n", *(mm->mmnew->useptr));
-               printf("*baseptr=%Fp    ", *baseptr); printf("*useptr=%Fp\n", *(mm->mmnew->useptr));
+       gvar->mm.mmnew->length = needed;
+       gvar->mm.mmnew->useptr = baseptr;
+       //if(gvar->mm.mmnew->useptr==NULL){
+#ifdef __DEBUG_MM__
+               printf("MM_GetPtr\n");
+               //%04x
+               printf("        baseptr=%Fp     ", baseptr); printf("useptr=%Fp\n", gvar->mm.mmnew->useptr);
+               printf("        *baseptr=%Fp    ", *baseptr); printf("*useptr=%Fp\n", *(gvar->mm.mmnew->useptr));
+               printf("        &baseptr=%Fp    ", &baseptr); printf("&useptr=%Fp\n", &(gvar->mm.mmnew->useptr));
 #endif
        //exit(-5); }
-       mm->mmnew->attributes = BASEATTRIBUTES;
+       gvar->mm.mmnew->attributes = BASEATTRIBUTES;
 
 //tryagain:
        for (search = 0; search<3; search++)
@@ -977,25 +964,25 @@ void MM_GetPtr (memptr *baseptr, dword size, mminfo_t *mm, mminfotype *mmi)
        // first search:        try to allocate right after the rover, then on up
        // second search:       search from the head pointer up to the rover
        // third search:        compress memory, then scan from start
-               if (search == 1 && mm->mmrover == mm->mmhead)
+               if (search == 1 && gvar->mm.mmrover == gvar->mm.mmhead)
                        search++;
 
                switch (search)
                {
                case 0:
-                       lastscan = mm->mmrover;
-                       scan = mm->mmrover->next;
+                       lastscan = gvar->mm.mmrover;
+                       scan = gvar->mm.mmrover->next;
                        endscan = NULL;
                        break;
                case 1:
-                       lastscan = mm->mmhead;
-                       scan = mm->mmhead->next;
-                       endscan = mm->mmrover;
+                       lastscan = gvar->mm.mmhead;
+                       scan = gvar->mm.mmhead->next;
+                       endscan = gvar->mm.mmrover;
                        break;
                case 2:
-                       MM_SortMem (mm);
-                       lastscan = mm->mmhead;
-                       scan = mm->mmhead->next;
+                       MM_SortMem (gvar);
+                       lastscan = gvar->mm.mmhead;
+                       scan = gvar->mm.mmhead->next;
                        endscan = NULL;
                        break;
                }
@@ -1012,16 +999,16 @@ void MM_GetPtr (memptr *baseptr, dword size, mminfo_t *mm, mminfotype *mmi)
                        // and allocate the new block
                        //
                                purge = lastscan->next;
-                               lastscan->next = mm->mmnew;
-                               mm->mmnew->start = *(unsigned *)baseptr = startseg;
-                               mm->mmnew->next = scan;
+                               lastscan->next = gvar->mm.mmnew;
+                               gvar->mm.mmnew->start = *(unsigned *)baseptr = startseg;
+                               gvar->mm.mmnew->next = scan;
                                while ( purge != scan)
                                {       // free the purgable block
                                        next = purge->next;
                                        FREEBLOCK(purge);
                                        purge = next;           // purge another if not at scan
                                }
-                               mm->mmrover = mm->mmnew;
+                               gvar->mm.mmrover = gvar->mm.mmnew;
                                return; // good allocation!
                        }
 
@@ -1040,18 +1027,18 @@ void MM_GetPtr (memptr *baseptr, dword size, mminfo_t *mm, mminfotype *mmi)
                }
        }
 
-       if (mm->bombonerror)
+       if (gvar->mm.bombonerror)
        {
 #ifdef __WATCOMC__
                //heapdump();
 #endif
-               printf(OUT_OF_MEM_MSG,(size-mmi->nearheap));
+               printf(OUT_OF_MEM_MSG,(size-gvar->mmi.nearheap));
                printf("for stability reasons the program will shut down! wwww\n");
-               MM_Shutdown(mm);
+               MM_Shutdown(gvar);
                exit(-1);
        }
        else
-               mm->mmerror = true;
+               gvar->mm.mmerror = true;
 }
 
 //==========================================================================
@@ -1066,16 +1053,16 @@ void MM_GetPtr (memptr *baseptr, dword size, mminfo_t *mm, mminfotype *mmi)
 ====================
 */
 
-void MM_FreePtr(memptr *baseptr, mminfo_t *mm)
+void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar)
 {
        //huge mmblocktype huge *scan,huge *last;
        mmblocktype far *scan,far *last;
 
-       last = mm->mmhead;
+       last = gvar->mm.mmhead;
        scan = last->next;
 
-       if(baseptr == mm->mmrover->useptr)      // removed the last allocated block
-               mm->mmrover = mm->mmhead;
+       if(baseptr == gvar->mm.mmrover->useptr) // removed the last allocated block
+               gvar->mm.mmrover = gvar->mm.mmhead;
 
        while(scan->useptr != baseptr && scan)
        {
@@ -1105,32 +1092,33 @@ void MM_FreePtr(memptr *baseptr, mminfo_t *mm)
 =====================
 */
 
-void MM_SetPurge(memptr *baseptr, int purge, mminfo_t *mm)
+
+void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar)
 {
        //huge mmblocktype huge *start;
        mmblocktype far *start;
 
-       start = mm->mmrover;
+       start = gvar->mm.mmrover;
 
        do
        {
-               if(mm->mmrover->useptr == baseptr)
+               if(gvar->mm.mmrover->useptr == baseptr)
                        break;
 
-               mm->mmrover = mm->mmrover->next;
+               gvar->mm.mmrover = gvar->mm.mmrover->next;
 
-               if(!mm->mmrover)
-                       mm->mmrover = mm->mmhead;
-               else if(mm->mmrover == start)
+               if(!gvar->mm.mmrover)
+                       gvar->mm.mmrover = gvar->mm.mmhead;
+               else if(gvar->mm.mmrover == start)
                {
-                       printf("MM_SetPurge: Block not found!");
-                       return;
+                       Quit("MM_SetPurge: Block not found!");
+                       //return;
                }
 
        } while(1);
 
-       mm->mmrover->attributes &= ~PURGEBITS;
-       mm->mmrover->attributes |= purge;
+       gvar->mm.mmrover->attributes &= ~PURGEBITS;
+       gvar->mm.mmrover->attributes |= purge;
 }
 
 //==========================================================================
@@ -1145,32 +1133,32 @@ void MM_SetPurge(memptr *baseptr, int purge, mminfo_t *mm)
 =====================
 */
 
-void MM_SetLock(memptr *baseptr, boolean locked, mminfo_t *mm)
+void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar)
 {
        //huge mmblocktype huge *start;
        mmblocktype far *start;
 
-       start = mm->mmrover;
+       start = gvar->mm.mmrover;
 
        do
        {
-               if(mm->mmrover->useptr == baseptr)
+               if(gvar->mm.mmrover->useptr == baseptr)
                        break;
 
-               mm->mmrover = mm->mmrover->next;
+               gvar->mm.mmrover = gvar->mm.mmrover->next;
 
-               if(!mm->mmrover)
-                       mm->mmrover = mm->mmhead;
-               else if(mm->mmrover == start)
+               if(!gvar->mm.mmrover)
+                       gvar->mm.mmrover = gvar->mm.mmhead;
+               else if(gvar->mm.mmrover == start)
                {
-                       printf("MM_SetLock: Block not found!");
-                       return;
+                       Quit("MM_SetLock: Block not found!");
+                       //return;
                }
 
        } while(1);
 
-       mm->mmrover->attributes &= ~LOCKBIT;
-       mm->mmrover->attributes |= locked*LOCKBIT;
+       gvar->mm.mmrover->attributes &= ~LOCKBIT;
+       gvar->mm.mmrover->attributes |= locked*LOCKBIT;
 }
 
 //==========================================================================
@@ -1185,7 +1173,7 @@ void MM_SetLock(memptr *baseptr, boolean locked, mminfo_t *mm)
 =====================
 */
 
-void MM_SortMem(mminfo_t *mm)
+void MM_SortMem(global_game_variables_t *gvar)
 {
        //huge mmblocktype huge *scan,huge *last,huge *next;
        mmblocktype far *scan,far *last,far *next;
@@ -1218,7 +1206,7 @@ void MM_SortMem(mminfo_t *mm)
        if(beforesort)
                beforesort();
 
-       scan = mm->mmhead;
+       scan = gvar->mm.mmhead;
 
        last = NULL;            // shut up compiler warning
 
@@ -1240,7 +1228,7 @@ void MM_SortMem(mminfo_t *mm)
                        //
                                next = scan->next;
                                FREEBLOCK(scan);
-                               //MM_FreeBlock(scan, mm);
+                               //MM_FreeBlock(scan, gvar);
                                last->next = next;
                                scan = next;
                                continue;
@@ -1275,7 +1263,7 @@ void MM_SortMem(mminfo_t *mm)
                scan = scan->next;              // go to next block
        }
 
-       mm->mmrover = mm->mmhead;
+       gvar->mm.mmrover = gvar->mm.mmhead;
 
        if(aftersort)
                aftersort();
@@ -1296,7 +1284,7 @@ void MM_SortMem(mminfo_t *mm)
 =====================
 */
 
-void MM_ShowMemory(global_game_variables_t *gvar,/*page_t *page, */mminfo_t *mm)
+void MM_ShowMemory(global_game_variables_t *gvar)
 {
        //huge mmblocktype huge *scan;
        mmblocktype far *scan;
@@ -1312,7 +1300,7 @@ void MM_ShowMemory(global_game_variables_t *gvar,/*page_t *page, */mminfo_t *mm)
 //++++mh       temp = bufferofs;
 //++++mh       bufferofs = 0;
 //**** VW_SetScreen (0,0);
-       scan = mm->mmhead;
+       scan = gvar->mm.mmhead;
        end = -1;
 
        CA_OpenDebug (gvar);
@@ -1429,14 +1417,14 @@ void MM_ShowMemory(global_game_variables_t *gvar,/*page_t *page, */mminfo_t *mm)
        /*strcpy(scratch1, AARESET);
        strcat(scratch1, "========================================\n");
        strcat(scratch1, "near=  ");
-       ultoa (*(mm->nearheap),str,10);
+       ultoa (*(gvar->mm.nearheap),str,10);
        strcat (scratch1,str);
        strcat(scratch1, "      far= ");
-       ultoa (*(mm->farheap),str,10);
+       ultoa (*(gvar->mm.farheap),str,10);
        strcat (scratch1,str);
        strcat(scratch1, "\n");
-       //strcat(scratch1, "&near=      %Fp ", &(mm->nearheap));
-       //strcat(scratch1, "&far=       %Fp", &(mm->farheap));
+       //strcat(scratch1, "&near=      %Fp ", &(gvar->mm.nearheap));
+       //strcat(scratch1, "&far=       %Fp", &(gvar->mm.farheap));
        //strcat(scratch1, "\n");
        strcat(scratch1, "========================================\n");
        write(gvar->handle.debughandle,scratch1,strlen(scratch1));*/
@@ -1459,7 +1447,7 @@ void MM_ShowMemory(global_game_variables_t *gvar,/*page_t *page, */mminfo_t *mm)
 =====================
 */
 
-void MM_DumpData(mminfo_t *mm)
+void MM_DumpData(global_game_variables_t *gvar)
 {
        //huge mmblocktype huge *scan,huge *best;
        mmblocktype far *scan,far *best;
@@ -1468,7 +1456,7 @@ void MM_DumpData(mminfo_t *mm)
        byte    lock,purge;
        FILE    *dumpfile;
 
-       free(mm->nearheap);
+       free(gvar->mm.nearheap);
 #ifdef __BORLANDC__
                dumpfile = fopen ("mmdump.16b","w");
 #endif
@@ -1486,7 +1474,7 @@ void MM_DumpData(mminfo_t *mm)
                oldlowest = lowest;
                lowest = 0xffff;
 
-               scan = mm->mmhead;
+               scan = gvar->mm.mmhead;
                while (scan)
                {
                        owner = (unsigned)scan->useptr;
@@ -1533,14 +1521,14 @@ void MM_DumpData(mminfo_t *mm)
 ======================
 */
 
-dword MM_UnusedMemory(mminfo_t *mm)
+dword MM_UnusedMemory(global_game_variables_t *gvar)
 {
        dword free;
        //huge mmblocktype huge *scan;
        mmblocktype far *scan;
 
        free = 0;
-       scan = mm->mmhead;
+       scan = gvar->mm.mmhead;
 
        while(scan->next)
        {
@@ -1565,14 +1553,14 @@ dword MM_UnusedMemory(mminfo_t *mm)
 ======================
 */
 
-dword MM_TotalFree(mminfo_t *mm)
+dword MM_TotalFree(global_game_variables_t *gvar)
 {
        dword free;
        //huge mmblocktype huge *scan;
        mmblocktype far *scan;
 
        free = 0;
-       scan = mm->mmhead;
+       scan = gvar->mm.mmhead;
 
        while(scan->next)
        {
@@ -1596,28 +1584,32 @@ dword MM_TotalFree(mminfo_t *mm)
 =====================
 */
 
-void MM_Report(global_game_variables_t *gvar)
+void MM_Report_(global_game_variables_t *gvar)
 {
        printf("========================================\n");
-       printf("                MM_Report\n");
+       printf("                MM_Report_\n");
        printf("========================================\n");
        if(MML_CheckForEMS())
        {
-               printf("        LIMEMS\n");
-               printf("                EMM v%x.%x available\n", gvar->mm.EMSVer>>4,gvar->mm.EMSVer&0x0F);
-               printf("                totalEMSpages:  %u      ", gvar->mm.totalEMSpages); printf("freeEMSpages:       %u\n", gvar->mm.freeEMSpages);
-               printf("                EMSpageframe:   %x\n", gvar->mm.EMSpageframe);
+               printf("        %cLIMEMS        %u\n", 0xC9, gvar->pm.emm.EMSPresent);
+               printf("        %c%cEMM v%x.%x available\n", 0xC7, 0xC4, gvar->pm.emm.EMSVer>>4,gvar->pm.emm.EMSVer&0x0F);
+               printf("        %c%ctotalEMSpages:      %u      ", 0xC7, 0xC4, gvar->pm.emm.totalEMSpages); printf("freeEMSpages:       %u\n", gvar->pm.emm.freeEMSpages);
+               printf("        %c%cEMSPageFrame:       %04x\n", 0xC7, 0xC4, gvar->pm.emm.EMSPageFrame);
+               printf("        %c%cEMSmem:     %lu\n", 0xD3, 0xC4, gvar->mmi.EMSmem);
        }
-       if(MML_CheckForXMS(&(gvar->mm)))
+       if(MML_CheckForXMS())
        {
-               printf("        XMS\n");
-               printf("                XMSaddr:        %X\n", *XMSaddr);
+               printf("        %cXMS   %u\n", 0xC9, gvar->pm.xmm.XMSPresent);
+               printf("        %c%cXMS v%x.%x available\n", 0xC7, 0xC4, XMSVer>>8,XMSVer&0x0F);
+               printf("        %c%cXMSDriver:  %Fp\n", 0xC7, 0xC4, XMSDriver);
+               printf("        %c%cXMSHandle:  %04x\n", 0xC7, 0xC4, gvar->pm.xmm.XMSHandle);
+               printf("        %c%cXMSmem:     %lu\n", 0xD3, 0xC4, gvar->mmi.XMSmem);
        }
-       printf("near:   %lu     ", gvar->mmi.nearheap); printf("far:    %lu\n", gvar->mmi.farheap); if(MML_CheckForEMS())
-       printf("EMSmem: %lu     ", gvar->mmi.EMSmem); if(MML_CheckForXMS(&(gvar->mm))) printf("XMSmem:  %lu", gvar->mmi.XMSmem); printf("\n");
+       printf("        %cConv. %u\n", 0xC9, gvar->pm.mm.MainPresent); DebugMemory_(gvar, 0);
        //printf("mainmem:      %lu\n", gvar->mmi.mainmem);
-       printf("Total convmem:  %lu     ", gvar->mmi.mainmem); printf("TotalFree:       %lu     ", MM_TotalFree(&(gvar->mm))); printf("TotalUsed:       %lu\n", gvar->mmi.mainmem+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem);
-       printf("                        UnusedMemory:   %lu\n", MM_UnusedMemory(&(gvar->mm)));
+       //printf("Total convmem:        %lu     ", gvar->mmi.mainmem); printf("TotalFree:       %lu     ", MM_TotalFree(gvar)+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem); printf("TotalUsed:   %lu\n", gvar->mmi.mainmem);
+       //printf("                      UnusedMemory:   %lu\n", MM_UnusedMemory(gvar));
+       printf("nearheap:       %lu             ", gvar->mmi.nearheap); printf("farheap:        %lu\n", gvar->mmi.farheap);
 }
 
 //==========================================================================
@@ -1761,32 +1753,41 @@ void MM_EMSerr(byte *stri, byte err)
 =====================
 */
 
-void MM_BombOnError(boolean bomb, mminfo_t *mm)
+void MM_BombOnError(boolean bomb, global_game_variables_t *gvar)
 {
-       mm->bombonerror = bomb;
+       gvar->mm.bombonerror = bomb;
 }
 
-/*void MM_GetNewBlock(mminfo_t *mm)
+/*void MM_GetNewBlock(global_game_variables_t *gvar)
 {
-       if(!mm->mmfree)
-               MML_ClearBlock(mm);
-       mm->mmnew=mm->mmfree;
-       mm->mmfree=mm->mmfree->next;
-       if(!(mm->mmnew=mm->mmfree))
+       if(!gvar->mm.mmfree)
+               MML_ClearBlock(gvar);
+       gvar->mm.mmnew=gvar->mm.mmfree;
+       gvar->mm.mmfree=gvar->mm.mmfree->next;
+       if(!(gvar->mm.mmnew=gvar->mm.mmfree))
        {
                printf("MM_GETNEWBLOCK: No free blocks!\n");
                return;
        }
-       mm->mmfree=mm->mmfree->next;
+       gvar->mm.mmfree=gvar->mm.mmfree->next;
 }
 
-void MM_FreeBlock(mmblocktype *x, mminfo_t *mm)
+void MM_FreeBlock(mmblocktype *x, global_game_variables_t *gvar)
 {
        x->useptr=NULL;
-       x->next=mm->mmfree;
-       mm->mmfree=x;
+       x->next=gvar->mm.mmfree;
+       gvar->mm.mmfree=x;
 }*/
 
+void xms_call(byte v, global_game_variables_t *gvar)
+{
+       dword XMSDriver = gvar->pm.xmm.XMSDriver;
+       __asm {
+               mov     ah,[v]
+               call [DWORD PTR XMSDriver]
+       }
+}
+
 /*void MM_seguin(void)
 {
        __asm {
index 3b1eac3d5510c83d39ea53f6c64abaa4baabbb56..b68eea9c472ba0055b8484bff1f45c5e78dddbb3 100755 (executable)
-/* Catacomb Apocalypse Source Code
- * Copyright (C) 1993-2014 Flat Rock Software
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-// ID_MM.H
-
-#ifndef __16_EXMM__
-#define __16_EXMM__
-
-#include <string.h>
-#include <malloc.h>
-#include "src/lib/16_head.h"
-#include "src/lib/16_hc.h"
-//#include "src/lib/modex16.h"
-//++++mh       #include "src/lib/16_in.h"
-
-#ifdef __DEBUG__               // 1 == Debug/Dev  ;  0 == Production/final
-#define OUT_OF_MEM_MSG "MM_GetPtr: Out of memory!\nYou were short :%lu bytes\n"
-#else
-#define OUT_OF_MEM_MSG "\npee\n"
-#endif
-
-//#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!") ;mmfree=mmfree->next;}
-#define GETNEWBLOCK {if(!mm->mmfree)MML_ClearBlock(mm);mm->mmnew=mm->mmfree;mm->mmfree=mm->mmfree->next;}
-
-#define FREEBLOCK(x) {*x->useptr=NULL;x->next=mm->mmfree;mm->mmfree=x;}
-
-#define SAVENEARHEAP   0x200           // space to leave in data segment
-#define SAVEFARHEAP    0//x400                 // space to leave in far heap
-
-#define        BUFFERSIZE              0x1000          // miscelanious, allways available buffer
-
-//moved to typdefst
-//#define MAXBLOCKS            1024
-
-
-
-//--------
-
-#define        EMS_INT                 0x67
-
-#define        EMS_STATUS              0x40
-#define        EMS_GETFRAME    0x41
-#define        EMS_GETPAGES    0x42
-#define        EMS_ALLOCPAGES  0x43
-#define        EMS_MAPPAGE             0x44
-#define        EMS_MAPXPAGE            0x50
-#define        EMS_FREEPAGES   0x45
-#define        EMS_VERSION             0x46
-
-//--------
-
-#define        XMS_VERSION             0x00
-
-#define        XMS_ALLOCHMA    0x01
-#define        XMS_FREEHMA             0x02
-
-#define        XMS_GENABLEA20  0x03
-#define        XMS_GDISABLEA20 0x04
-#define        XMS_LENABLEA20  0x05
-#define        XMS_LDISABLEA20 0x06
-#define        XMS_QUERYA20    0x07
-
-#define        XMS_QUERYREE    0x08
-#define        XMS_ALLOC               0x09
-#define        XMS_FREE                0x0A
-#define        XMS_MOVE                0x0B
-#define        XMS_LOCK                0x0C
-#define        XMS_UNLOCK              0x0D
-#define        XMS_GETINFO             0x0E
-#define        XMS_RESIZE              0x0F
-
-#define        XMS_ALLOCUMB    0x10
-#define        XMS_FREEUMB             0x11
-
-//==========================================================================
-
-//moved to typdefst
-/*typedef struct
-{
-       dword   nearheap,farheap,EMSmem,XMSmem,mainmem;
-} mminfotype;*/
-
-//==========================================================================
-
-extern void            (* beforesort) (void);
-extern void            (* aftersort) (void);
-extern void            (* XMSaddr) (void);             // far pointer to XMS driver
-
-//==========================================================================
-
-/*
-=============================================================================
-
-                                                       LOCAL INFO
-
-=============================================================================
-*/
-
-#define LOCKBIT                0x80    // if set in attributes, block cannot be moved
-#define PURGEBITS      3               // 0-3 level, 0= unpurgable, 3= purge first
-#define PURGEMASK      0xfffc
-#define BASEATTRIBUTES 0       // unlocked, non purgable
-
-//moved to typedefst
-//#define MAXUMBS              12
-#define MAPPAGES               4//mm->EMSpagesmapped
-
-//moved to typdefst
-/*typedef struct mmblockstruct
-{
-       word    start,length;
-       //word  start;  dword length;
-       word    blob;   //for data larger than 64k
-       unsigned        attributes;
-       memptr          *useptr;        // pointer to the segment start
-       //huge struct mmblockstruct huge *next;
-       struct mmblockstruct far *next;
-} mmblocktype;
-
-
-typedef struct
-{
-       memptr bufferseg;
-       boolean         mmstarted, bombonerror, mmerror;
-       //huge void huge        *farheap;
-       void far        *farheap;
-#ifdef __BORLANDC__
-       void    *nearheap;
-#endif
-#ifdef __WATCOMC__
-       void __near     *nearheap;
-#endif
-       //byte          EMS_status;
-       unsigned        totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;
-       unsigned int EMSVer;
-       word numUMBs,UMBbase[MAXUMBS];
-       //dword numUMBs,UMBbase[MAXUMBS];
-       //huge mmblocktype      huge mmblocks[MAXBLOCKS],huge *mmhead,huge *mmfree,huge *mmrover,huge *mmnew;
-       mmblocktype     far mmblocks[MAXBLOCKS],far *mmhead,far *mmfree,far *mmrover,far *mmnew;
-} mminfo_t;*/
-
-/*
-=============================================================================
-
-                                                GLOBAL VARIABLES
-
-=============================================================================
-*/
-
-
-/*
-=============================================================================
-
-                                                LOCAL VARIABLES
-
-=============================================================================
-*/
-
-//==========================================================================
-
-boolean MML_CheckForEMS(void);
-byte MML_SetupEMS(mminfo_t *mm);
-void MML_ShutdownEMS(mminfo_t *mm);
-byte MM_MapEMS(mminfo_t *mm, mminfotype *mmi);
-byte MM_MapXEMS(mminfo_t *mm, mminfotype *mmi);
-boolean MML_CheckForXMS(mminfo_t *mm);
-void MML_SetupXMS(mminfo_t *mm, mminfotype *mmi);
-void MML_ShutdownXMS(mminfo_t *mm);
-void MML_UseSpace(word segstart, dword seglength, mminfo_t *mm);
-void MML_ClearBlock(mminfo_t *mm);
-
-void MM_Startup(mminfo_t *mm, mminfotype *mmi);
-void MM_Shutdown(mminfo_t *mm);
-
-void MM_GetPtr(memptr *baseptr,dword size, mminfo_t *mm, mminfotype *mmi);
-void MM_FreePtr(memptr *baseptr, mminfo_t *mm);
-void MM_SetPurge(memptr *baseptr, int purge, mminfo_t *mm);
-void MM_SetLock(memptr *baseptr, boolean locked, mminfo_t *mm);
-void MM_SortMem(mminfo_t *mm);
-void MM_ShowMemory(global_game_variables_t *gvar,/*page_t *page, */mminfo_t *mm);
-void MM_DumpData(mminfo_t *mm);
-dword MM_UnusedMemory(mminfo_t *mm);
-dword MM_TotalFree(mminfo_t *mm);
-void MM_Report(global_game_variables_t *gvar);
-static void MM_EMSerr(byte *stri, byte err);
-void MM_BombOnError(boolean bomb, mminfo_t *mm);
-//void MM_GetNewBlock(mminfo_t *mm);
-//void MM_FreeBlock(mmblocktype *x, mminfo_t *mm);
-
-//==========================================================================
-
-#endif
+/* Catacomb Apocalypse Source Code\r
+ * Copyright (C) 1993-2014 Flat Rock Software\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ */\r
+\r
+// ID_MM.H\r
+\r
+#ifndef __16_EXMM__\r
+#define __16_EXMM__\r
+\r
+#include <string.h>\r
+#include <malloc.h>\r
+#include "src/lib/16_head.h"\r
+#include "src/lib/16_hc.h"\r
+#include "src/lib/16_tail.h"\r
+//++++mh       #include "src/lib/16_in.h"\r
+\r
+#ifdef __DEBUG__               // 1 == Debug/Dev  ;  0 == Production/final\r
+#define OUT_OF_MEM_MSG "MM_GetPtr: Out of memory!\nYou were short :%lu bytes\n"\r
+extern boolean dbg_debugpm;\r
+#else\r
+#define OUT_OF_MEM_MSG "\npee\n"\r
+#endif\r
+\r
+//#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!") ;mmfree=mmfree->next;}\r
+#define GETNEWBLOCK {if(!gvar->mm.mmfree)MML_ClearBlock(gvar);gvar->mm.mmnew=gvar->mm.mmfree;gvar->mm.mmfree=gvar->mm.mmfree->next;}\r
+\r
+#define FREEBLOCK(x) {*x->useptr=NULL;x->next=gvar->mm.mmfree;gvar->mm.mmfree=x;}\r
+\r
+#define SAVENEARHEAP   0x200           // space to leave in data segment\r
+#define SAVEFARHEAP    0//x400                 // space to leave in far heap\r
+\r
+#define        BUFFERSIZE              0x1000          // miscelanious, allways available buffer\r
+\r
+//moved to typdefst\r
+//#define MAXBLOCKS            1024\r
+\r
+\r
+\r
+//--------\r
+\r
+#define        EMS_INT                 0x67\r
+#define        EMM_INT                 0x21\r
+\r
+#define        EMS_STATUS              0x40\r
+#define        EMS_GETFRAME    0x41\r
+#define        EMS_GETPAGES    0x42\r
+#define        EMS_ALLOCPAGES  0x43\r
+#define        EMS_MAPPAGE             0x44\r
+#define        EMS_MAPXPAGE            0x50\r
+#define        EMS_FREEPAGES   0x45\r
+#define        EMS_VERSION             0x46\r
+\r
+//--------\r
+\r
+#define        XMS_INT                 0x2f\r
+#define        XMS_CALL(v)             _AH = (v);\\r
+                                               __asm call [DWORD PTR XMSDriver]\r
+/*__asm { mov ah,[v]\*///}\r
+\r
+#define        XMS_VERSION             0x00\r
+\r
+#define        XMS_ALLOCHMA            0x01\r
+#define        XMS_FREEHMA             0x02\r
+\r
+#define        XMS_GENABLEA20  0x03\r
+#define        XMS_GDISABLEA20 0x04\r
+#define        XMS_LENABLEA20  0x05\r
+#define        XMS_LDISABLEA20 0x06\r
+#define        XMS_QUERYA20            0x07\r
+\r
+#define        XMS_QUERYFREE   0x08\r
+#define        XMS_ALLOC               0x09\r
+#define        XMS_FREE                        0x0A\r
+#define        XMS_MOVE                        0x0B\r
+#define        XMS_LOCK                        0x0C\r
+#define        XMS_UNLOCK              0x0D\r
+#define        XMS_GETINFO             0x0E\r
+#define        XMS_RESIZE              0x0F\r
+\r
+#define        XMS_ALLOCUMB            0x10\r
+#define        XMS_FREEUMB             0x11\r
+\r
+//==========================================================================\r
+\r
+//moved to typdefst\r
+/*typedef struct\r
+{\r
+       dword   nearheap,farheap,EMSmem,XMSmem,mainmem;\r
+} mminfotype;*/\r
+\r
+//==========================================================================\r
+\r
+extern void            (* beforesort) (void);\r
+extern void            (* aftersort) (void);\r
+extern void            (* XMSaddr) (void);             // far pointer to XMS driver\r
+extern dword   XMSDriver;\r
+extern word            XMSVer;\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                       LOCAL INFO\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define LOCKBIT                0x80    // if set in attributes, block cannot be moved\r
+#define PURGEBITS      3               // 0-3 level, 0= unpurgable, 3= purge first\r
+#define PURGEMASK      0xfffc\r
+#define BASEATTRIBUTES 0       // unlocked, non purgable\r
+\r
+//moved to typedefst\r
+//#define MAXUMBS              12\r
+#define MAPPAGES               4//gvar->mm.EMSpagesmapped\r
+\r
+//moved to typdefst\r
+/*typedef struct mmblockstruct\r
+{\r
+       word    start,length;\r
+       //word  start;  dword length;\r
+       word    blob;   //for data larger than 64k\r
+       unsigned        attributes;\r
+       memptr          *useptr;        // pointer to the segment start\r
+       //huge struct mmblockstruct huge *next;\r
+       struct mmblockstruct far *next;\r
+} mmblocktype;\r
+\r
+\r
+typedef struct\r
+{\r
+       memptr bufferseg;\r
+       boolean         mmstarted, bombonerror, mmerror;\r
+       //huge void huge        *farheap;\r
+       void far        *farheap;\r
+#ifdef __BORLANDC__\r
+       void    *nearheap;\r
+#endif\r
+#ifdef __WATCOMC__\r
+       void __near     *nearheap;\r
+#endif\r
+       //byte          EMS_status;\r
+       unsigned        totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;\r
+       unsigned int EMSVer;\r
+       word numUMBs,UMBbase[MAXUMBS];\r
+       //dword numUMBs,UMBbase[MAXUMBS];\r
+       //huge mmblocktype      huge mmblocks[MAXBLOCKS],huge *mmhead,huge *mmfree,huge *mmrover,huge *mmnew;\r
+       mmblocktype     far mmblocks[MAXBLOCKS],far *mmhead,far *mmfree,far *mmrover,far *mmnew;\r
+} mminfo_t;*/\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+//==========================================================================\r
+\r
+boolean MML_CheckForEMS(void);\r
+//byte MML_SetupEMS(mminfo_t *mm);\r
+//void MML_ShutdownEMS(mminfo_t *mm);\r
+byte MM_MapEMS(global_game_variables_t *gvar);\r
+//byte MM_MapXEMS(global_game_variables_t *gvar);\r
+boolean MML_CheckForXMS(void);\r
+//void MML_SetupXMS(mminfo_t *mm, mminfotype *mmi);\r
+//void MML_ShutdownXMS(mminfo_t *mm);\r
+void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar);\r
+void MML_ClearBlock(global_game_variables_t *gvar);\r
+\r
+void MM_Startup(global_game_variables_t *gvar);\r
+void MM_Shutdown(global_game_variables_t *gvar);\r
+\r
+void MM_GetPtr(memptr *baseptr,dword size, global_game_variables_t *gvar);\r
+void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar);\r
+void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar);\r
+void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar);\r
+void MM_SortMem(global_game_variables_t *gvar);\r
+void MM_ShowMemory(global_game_variables_t *gvar);\r
+void MM_DumpData(global_game_variables_t *gvar);\r
+dword MM_UnusedMemory(global_game_variables_t *gvar);\r
+dword MM_TotalFree(global_game_variables_t *gvar);\r
+void MM_Report_(global_game_variables_t *gvar);\r
+/*static */void MM_EMSerr(byte *stri, byte err);\r
+void MM_BombOnError(boolean bomb, global_game_variables_t *gvar);\r
+//void MM_GetNewBlock(mminfo_t *mm);\r
+//void MM_FreeBlock(mmblocktype *x, mminfo_t *mm);\r
+void xms_call(byte v, global_game_variables_t *gvar);\r
+\r
+//==========================================================================\r
+\r
+#endif\r
index bc9ba74c759fc091e2442664689cc7aa8658e32e..c9019b785e70d5dccfc76fdd6d50ab5c713b8a04 100755 (executable)
@@ -1,3 +1,25 @@
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
 //\r
 //     ID_PM.C\r
 //     Id Engine's Page Manager v1.0\r
 #include "src/lib/16_pm.h"\r
 #pragma hdrstop\r
 \r
+#ifdef __DEBUG__\r
+boolean dbg_debugpm=0;\r
+#endif\r
+\r
 //     Main Mem specific variables\r
-       boolean                 MainPresent;\r
-       memptr                  MainMemPages[PMMaxMainMem];\r
-       PMBlockAttr             MainMemUsed[PMMaxMainMem];\r
-       int                             MainPagesAvail;\r
+       //boolean                       MainPresent;\r
+/*     memptr                  MainMemPages[PMMaxMainMem];\r
+       PMBlockAttr             gvar->pm.mm.MainMemUsed[PMMaxMainMem];\r
+       int                             gvar->pm.mm.MainPagesAvail;*/\r
 \r
 //     EMS specific variables\r
-       boolean                 EMSPresent;\r
-       word                    EMSAvail,EMSPagesAvail,EMSHandle,\r
-                                       EMSPageFrame,EMSPhysicalPage;\r
-       EMSListStruct   EMSList[EMSFrameCount];\r
+       //boolean                       EMSPresent;\r
+/*     word                    gvar->pm.emm.EMSAvail,gvar->pm.emm.EMSPagesAvail,gvar->pm.emm.EMSHandle,\r
+                                       gvar->pm.emm.EMSPageFrame,gvar->pm.emm.EMSPhysicalPage;\r
+       gvar->pm.emm.EMSListStruct      gvar->pm.emm.EMSList[EMSFrameCount];*/\r
 \r
 //     XMS specific variables\r
-       boolean                 XMSPresent;\r
-       word                    XMSAvail,XMSPagesAvail,XMSHandle;\r
-       longword                XMSDriver;\r
-       int                             XMSProtectPage = -1;\r
+       //boolean                       XMSPresent;\r
+       //word                  gvar->pm.xmm.XMSAvail,gvar->pm.xmm.XMSPagesAvail,gvar->pm.xmm.XMSHandle;\r
+       dword                   XMSDriver;      //hard to put in gvar\r
+       word                            XMSVer; //hard to put in gvar\r
+/*     int                             gvar->pm.xmm.XMSProtectPage = -1;\r
 \r
 //     File specific variables\r
-       char                    PageFileName[13] = {"VSWAP."};\r
+       char                    gvar->pm.fi.PageFileName[13] = {"VSWAP."};\r
        int                             PageFile = -1;\r
-       word                    ChunksInFile;\r
-       word                    PMSpriteStart,PMSoundStart;\r
+       word                    gvar->pm.fi.ChunksInFile;\r
+       word                    PMSpriteStart,PMSoundStart;*/\r
 \r
 //     General usage variables\r
-       boolean                 PMStarted,\r
-                                       PMPanicMode,\r
-                                       PMThrashing;\r
-       word                    XMSPagesUsed,\r
-                                       EMSPagesUsed,\r
+/*     boolean                 PMStarted,\r
+                                       gvar->pm.PMPanicMode,\r
+                                       gvar->pm.PMThrashing;\r
+       word                    gvar->pm.XMSPagesUsed,\r
+                                       gvar->pm.EMSPagesUsed,\r
                                        MainPagesUsed,\r
-                                       PMNumBlocks;\r
+                                       gvar->pm.PMNumBlocks;\r
        long                    PMFrameCount;\r
-       PageListStruct  far *PMPages,\r
-                                       _seg *PMSegPages;\r
+       PageListStruct  far *gvar->pm.PMPages,\r
+                                       _seg *gvar->pm.PMSegPages;*/\r
 \r
 static char            *ParmStrings[] = {"nomain","noems","noxms",nil};\r
 \r
@@ -54,21 +81,50 @@ static      char            *ParmStrings[] = {"nomain","noems","noxms",nil};
 //\r
 //     PML_MapEMS() - Maps a logical page to a physical page\r
 //\r
-void\r
-PML_MapEMS(word logical,word physical)\r
-{
-       union REGS CPURegs;\r
-       CPURegs.h.al = physical;\r
-       CPURegs.x.bx = logical;\r
-       CPURegs.x.dx = EMSHandle;\r
-       CPURegs.h.ah = EMS_MAPPAGE;\r
-       __asm
-       {
-               int     EMS_INT
-       }\r
+byte\r
+PML_MapEMS(word logical, byte physical, global_game_variables_t *gvar)\r
+{\r
+       byte    err, str[160];\r
+       unsigned        EMShandle;\r
+       int     i;\r
 \r
-       if(CPURegs.h.ah)\r
-               printf("PML_MapEMS: Page mapping failed\n");\r
+       boolean errorflag=false;\r
+       EMShandle=gvar->pm.emm.EMSHandle;\r
+\r
+       __asm {\r
+               mov     ah,EMS_MAPPAGE\r
+               mov     al,physical\r
+               mov     bx,logical\r
+               mov     dx,EMShandle\r
+               int     EMS_INT\r
+               or      ah,ah\r
+               jnz     errorme\r
+               jmp     Endme\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               errorme:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     err,ah\r
+               mov     errorflag,1\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               Endme:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       if(errorflag==true)\r
+       {\r
+               strcpy(str,"MM_MapEMS: EMS error ");\r
+               MM_EMSerr(str, err);\r
+               printf("%s\n",str);\r
+               Quit("PML_MapEMS: Page mapping failed\n");\r
+               return err;\r
+       }\r
+       return 0;\r
 }\r
 \r
 //\r
@@ -80,108 +136,207 @@ PML_MapEMS(word logical,word physical)
 //                     to the maximum we need)\r
 //\r
 \r
-       char    EMMDriverName[9] = "EMMXXXX0";\r
-\r
 boolean\r
-PML_StartupEMS(void)\r
+PML_StartupEMS(global_game_variables_t *gvar)\r
 {\r
        int             i;\r
-       long    size;\r
-\r
-       EMSPresent = false;                     // Assume that we'll fail\r
-       EMSAvail = 0;\r
-\r
-       _DX = (word)EMMDriverName;\r
-       _AX = 0x3d00;\r
-       geninterrupt(0x21);                     // try to open EMMXXXX0 device\r
-asm    jnc     gothandle\r
-       goto error;\r
-\r
-gothandle:\r
-       _BX = _AX;\r
-       _AX = 0x4400;\r
-       geninterrupt(0x21);                     // get device info\r
-asm    jnc     gotinfo;\r
-       goto error;\r
-\r
-gotinfo:\r
-asm    and     dx,0x80\r
-       if (!_DX)\r
-               goto error;\r
-\r
-       _AX = 0x4407;\r
-       geninterrupt(0x21);                     // get status\r
-asm    jc      error\r
-       if (!_AL)\r
-               goto error;\r
-\r
-       _AH = 0x3e;\r
-       geninterrupt(0x21);                     // close handle\r
-\r
-       _AH = EMS_STATUS;\r
-       geninterrupt(EMS_INT);\r
-       if (_AH)\r
-               goto error;                             // make sure EMS hardware is present\r
-\r
-       _AH = EMS_VERSION;\r
-       geninterrupt(EMS_INT);\r
-       if (_AH || (_AL < 0x32))        // only work on EMS 3.2 or greater (silly, but...)\r
-               goto error;\r
-\r
-       _AH = EMS_GETFRAME;\r
-       geninterrupt(EMS_INT);\r
-       if (_AH)\r
-               goto error;                             // find the page frame address\r
-       EMSPageFrame = _BX;\r
-\r
-       _AH = EMS_GETPAGES;\r
-       geninterrupt(EMS_INT);\r
-       if (_AH)\r
-               goto error;\r
-       if (_BX < 2)\r
-               goto error;             // Require at least 2 pages (32k)\r
-       EMSAvail = _BX;\r
-\r
-       // Don't hog all available EMS\r
-       size = EMSAvail * (long)EMSPageSize;\r
-       if (size - (EMSPageSize * 2) > (ChunksInFile * (long)PMPageSize))\r
+       //long  size;\r
+       byte    err, str[64];\r
+\r
+       boolean errorflag=false;\r
+       static char     emmname[] = "EMMXXXX0"; //fix by andrius4669\r
+       unsigned int EMSVer = 0;\r
+       unsigned        totalEMSpages,freeEMSpages,EMSPageFrame,EMSHandle,EMSAvail;\r
+       totalEMSpages = freeEMSpages = EMSPageFrame = 0;\r
+       gvar->pm.emm.EMSPresent = false;                        // Assume that we'll fail\r
+       gvar->pm.emm.EMSAvail = 0;\r
+       gvar->mmi.EMSmem = 0;\r
+\r
+       __asm {\r
+               mov     dx,OFFSET emmname       //fix by andrius4669\r
+               mov     ax,0x3d00\r
+               int     EMM_INT         // try to open EMMXXXX0 device\r
+               jc      error1\r
+\r
+               mov     bx,ax\r
+               mov     ax,0x4400\r
+\r
+               int     EMM_INT         // get device info\r
+               jc      error1\r
+\r
+               and     dx,0x80\r
+               jz      error1\r
+\r
+               mov     ax,0x4407\r
+\r
+               int     EMM_INT         // get status\r
+               jc      error1\r
+               or      al,al\r
+               jz      error1\r
+\r
+               mov     ah,0x3e\r
+               int     EMM_INT         // close handle\r
+               jc      error1\r
+\r
+               mov     ah,EMS_STATUS\r
+               int     EMS_INT\r
+               jc      error1                  // make sure EMS hardware is present\r
+\r
+               mov     ah,EMS_VERSION\r
+               int     EMS_INT                 // only work on EMS 3.2 or greater (silly, but...)\r
+               or      ah,ah\r
+               jnz     error1\r
+               mov     [EMSVer],ax             //      set EMSVer\r
+               cmp     al,0x32                 // only work on ems 3.2 or greater\r
+               jb      error1\r
+\r
+               mov     ah,EMS_GETFRAME\r
+               int     EMS_INT                 // find the page frame address\r
+               or      ah,ah\r
+               jnz     error1\r
+               mov     [EMSPageFrame],bx\r
+\r
+               mov     ah,EMS_GETPAGES\r
+               int     EMS_INT                 // find out how much EMS is there\r
+               or      ah,ah\r
+               jnz     error1\r
+               or      bx,bx\r
+               jz      noEMS                   // no EMS at all to allocate\r
+               cmp     bx,2\r
+               jl      noEMS                   // Require at least 2 pages (32k)\r
+               mov     [totalEMSpages],dx\r
+               mov     [freeEMSpages],bx\r
+               mov     [EMSAvail],bx\r
+               jmp End1\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       error1:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     err,ah\r
+               mov     errorflag,1\r
+               jmp End1\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+noEMS:\r
+End1:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+/*\r
+       if(errorflag==false)\r
        {\r
-               size = (ChunksInFile * (long)PMPageSize) + EMSPageSize;\r
-               EMSAvail = size / EMSPageSize;\r
+               // Don't hog all available EMS\r
+               size = gvar->pm.emm.EMSAvail * (long)EMSPageSize;\r
+               if (size - (EMSPageSize * 2) > (gvar->pm.fi.ChunksInFile * (long)PMPageSize))\r
+               {\r
+                       size = (gvar->pm.fi.ChunksInFile * (long)PMPageSize) + EMSPageSize;\r
+                       gvar->pm.emm.EMSAvail = size / EMSPageSize;\r
+               }\r
        }\r
+*/\r
+       __asm {\r
+               mov     ah,EMS_ALLOCPAGES\r
+               mov     bx,[EMSAvail];\r
+               int     EMS_INT\r
+               or      ah,ah\r
+               jnz     error2\r
+               mov     [EMSHandle],dx\r
+               jmp     End2\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       error2:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     err,ah\r
+               mov     errorflag,1\r
+               jmp End2\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+End2:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
 \r
-       _AH = EMS_ALLOCPAGES;\r
-       _BX = EMSAvail;\r
-       geninterrupt(EMS_INT);\r
-       if (_AH)\r
-               goto error;\r
-       EMSHandle = _DX;\r
-\r
-       mminfo.EMSmem += EMSAvail * (long)EMSPageSize;\r
+       if(errorflag==false)\r
+       {\r
+       gvar->mmi.EMSmem = EMSAvail * (dword)EMSPageSize;\r
 \r
        // Initialize EMS mapping cache\r
        for (i = 0;i < EMSFrameCount;i++)\r
-               EMSList[i].baseEMSPage = -1;\r
+               gvar->pm.emm.EMSList[i].baseEMSPage = -1;\r
 \r
-       EMSPresent = true;                      // We have EMS\r
+       }\r
+       else\r
+       {\r
+               strcpy(str,"PML_StartupEMS: EMS error ");\r
+               MM_EMSerr(str, err);\r
+               printf("%s\n",str);\r
+               return(gvar->pm.emm.EMSPresent);\r
+       }\r
 \r
-error:\r
-       return(EMSPresent);\r
+       gvar->pm.emm.EMSPresent = true;                 // We have EMS\r
+       gvar->pm.emm.EMSPageFrame = EMSPageFrame;\r
+       gvar->pm.emm.EMSAvail = EMSAvail;\r
+       gvar->pm.emm.EMSVer = EMSVer;\r
+       gvar->pm.emm.EMSHandle = EMSHandle;\r
+       gvar->pm.emm.freeEMSpages = freeEMSpages;\r
+       gvar->pm.emm.totalEMSpages = totalEMSpages;\r
+\r
+       return(gvar->pm.emm.EMSPresent);\r
 }\r
 \r
 //\r
 //     PML_ShutdownEMS() - If EMS was used, deallocate it\r
 //\r
 void\r
-PML_ShutdownEMS(void)\r
+PML_ShutdownEMS(global_game_variables_t *gvar)\r
 {\r
-       if (EMSPresent)\r
+       word EMSHandle;\r
+       byte err,str[64];\r
+\r
+       boolean errorflag=false;\r
+       EMSHandle=gvar->pm.emm.EMSHandle;\r
+\r
+       if (gvar->pm.emm.EMSPresent)\r
        {\r
-       asm     mov     ah,EMS_FREEPAGES\r
-       asm     mov     dx,[EMSHandle]\r
-       asm     int     EMS_INT\r
-               if (_AH)\r
-                       printf("PML_ShutdownEMS: Error freeing EMS\n");\r
+               __asm {\r
+                       mov     ah,EMS_FREEPAGES\r
+                       mov     dx,[EMSHandle]\r
+                       int     EMS_INT\r
+                       jc      errores\r
+                       jmp     Endes\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       errores:\r
+#ifdef __BORLANDC__\r
+               __asm {\r
+#endif\r
+                       mov     err,ah\r
+                       mov     errorflag,1\r
+                       jmp     Endes\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       Endes:\r
+#ifdef __WATCOMC__\r
+               }\r
+#endif\r
+               if(errorflag==true)\r
+               {\r
+                       strcpy(str,"PML_ShutdownEMS: Error freeing EMS ");\r
+                       MM_EMSerr(str, err);\r
+                       printf("%s\n",str);\r
+                       Quit("PML_ShutdownEMS: Error freeing EMS\n");\r
+                       //return;\r
+               }\r
        }\r
 }\r
 \r
@@ -198,46 +353,146 @@ PML_ShutdownEMS(void)
 //             Allocates any remaining XMS (rounded down to the nearest page size)\r
 //\r
 boolean\r
-PML_StartupXMS(void)\r
+PML_StartupXMS(global_game_variables_t *gvar)\r
 {\r
-       XMSPresent = false;                                     // Assume failure\r
-       XMSAvail = 0;\r
-\r
-asm    mov     ax,0x4300\r
-asm    int     XMS_INT                                         // Check for presence of XMS driver\r
-       if (_AL != 0x80)\r
-               goto error;\r
-\r
-\r
-asm    mov     ax,0x4310\r
-asm    int     XMS_INT                                                 // Get address of XMS driver\r
-asm    mov     [WORD PTR XMSDriver],bx\r
-asm    mov     [WORD PTR XMSDriver+2],es               // function pointer to XMS driver\r
-\r
+//TODO: translate the _REG into working assembly\r
+//#define STARTUPXMSASM\r
+       byte err;\r
+       word XMSAvail, XMSHandle;//, XMSVer;\r
+       boolean errorflag=false;\r
+       word e=0;\r
+       gvar->pm.xmm.XMSPresent = false;                                        // Assume failure\r
+       XMSAvail = gvar->mmi.XMSmem = 0;\r
+\r
+       __asm {\r
+               mov     ax,0x4300\r
+               int     XMS_INT                                         // Check for presence of XMS driver\r
+               cmp     al,0x80\r
+               jne     error1\r
+               mov     e,1\r
+\r
+               mov     ax,0x4310\r
+               int     XMS_INT                                                 // Get address of XMS driver\r
+               mov     [WORD PTR XMSDriver],bx\r
+               mov     [WORD PTR XMSDriver+2],es               // function pointer to XMS driver\r
+\r
+               mov     ah,XMS_VERSION\r
+               call    [DWORD PTR XMSDriver]                                           //; Get XMS Version Number\r
+               mov     [XMSVer],ax\r
+               mov     e,2\r
+\r
+#ifdef STARTUPXMSASM\r
+               mov     ah,XMS_QUERYFREE                        // Find out how much XMS is available\r
+               call    [DWORD PTR XMSDriver]\r
+               mov     XMSAvail,ax\r
+               or      ax,ax                           // AJR: bugfix 10/8/92\r
+               jz      error1\r
+               mov     e,3\r
+#endif\r
+               jmp     End1\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       error1:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     err,bl\r
+               mov     errorflag,1\r
+               jmp End1\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+End1:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       if(errorflag==true) goto error;\r
+#ifndef STARTUPXMSASM\r
        XMS_CALL(XMS_QUERYFREE);                        // Find out how much XMS is available\r
        XMSAvail = _AX;\r
        if (!_AX)                               // AJR: bugfix 10/8/92\r
+       {\r
+               errorflag = true;\r
+               err = _BL;\r
                goto error;\r
+       }\r
+       e++;\r
+#endif\r
 \r
+#ifdef __DEBUG_PM__\r
+       printf("XMSVer=%02X     ", XMSVer);\r
+       printf("XMSAvail=%u\n", XMSAvail);\r
+       getch();\r
+#endif\r
        XMSAvail &= ~(PMPageSizeKB - 1);        // Round off to nearest page size\r
        if (XMSAvail < (PMPageSizeKB * 2))      // Need at least 2 pages\r
+       {\r
+               errorflag=true;\r
                goto error;\r
-\r
+       }\r
+#ifdef STARTUPXMSASM\r
+       __asm {\r
+               mov     dx,XMSAvail\r
+               mov     ah,XMS_ALLOC                            // And do the allocation\r
+               call    [DWORD PTR XMSDriver]\r
+               mov     XMSHandle,dx\r
+               or      ax,ax                           // AJR: bugfix 10/8/92\r
+               jz      error2\r
+               mov     e,4\r
+               jmp     End2\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       error2:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     err,bl\r
+               mov     errorflag,1\r
+               jmp End2\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+End2:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+#else\r
        _DX = XMSAvail;\r
        XMS_CALL(XMS_ALLOC);                            // And do the allocation\r
        XMSHandle = _DX;\r
-\r
        if (!_AX)                               // AJR: bugfix 10/8/92\r
        {\r
-               XMSAvail = 0;\r
+               errorflag=true;\r
+               err = _BL;\r
                goto error;\r
        }\r
-\r
-       mminfo.XMSmem += XMSAvail * 1024;\r
-\r
-       XMSPresent = true;\r
+       e++;\r
+#endif\r
 error:\r
-       return(XMSPresent);\r
+       if(errorflag==false)\r
+       {\r
+               gvar->mmi.XMSmem = (dword)(XMSAvail) * 1024;\r
+               gvar->pm.xmm.XMSAvail = XMSAvail;\r
+               gvar->pm.xmm.XMSHandle = XMSHandle;\r
+               //gvar->pm.xmm.XMSVer = XMSVer;\r
+               gvar->pm.xmm.XMSPresent = true;\r
+#ifdef __DEBUG_PM__\r
+               printf("        XMSmem=%lu      XMSAvail=%u\n", gvar->mmi.XMSmem, XMSAvail);\r
+#endif\r
+       }\r
+       else\r
+       {\r
+#ifdef __DEBUG_PM__\r
+               //printf("XMSHandle\n");\r
+               //printf("      1=%u    2=%u    3=%u    4=%u\n", XMSHandle1, XMSHandle2, XMSHandle3, XMSHandle4);\r
+               //printf("      2=%u    ", XMSHandle);\r
+               //printf("      %u", gvar->pm.xmm.XMSHandle);\r
+               printf("        err=%02X        e=%u\n", err, e);\r
+#endif\r
+       }\r
+       return(gvar->pm.xmm.XMSPresent);\r
 }\r
 \r
 //\r
@@ -245,49 +500,59 @@ error:
 //             Will round an odd-length request up to the next even value\r
 //\r
 void\r
-PML_XMSCopy(boolean toxms,byte far *addr,word xmspage,word length)\r
+PML_XMSCopy(boolean toxms,byte far *addr,word xmspage,word length, global_game_variables_t *gvar)\r
 {\r
        dword   xoffset;\r
        struct\r
        {\r
-               longword        length;\r
+               dword   length;\r
                word            source_handle;\r
-               longword        source_offset;\r
+               dword   source_offset;\r
                word            target_handle;\r
-               longword        target_offset;\r
+               dword   target_offset;\r
        } copy;\r
 \r
        if (!addr)\r
-               printf("PML_XMSCopy: zero address\n");\r
+       {\r
+               Quit("PML_XMSCopy: zero address\n");\r
+               //return;\r
+       }\r
 \r
-       xoffset = (longword)xmspage * PMPageSize;\r
+       xoffset = (dword)xmspage * PMPageSize;\r
 \r
        copy.length = (length + 1) & ~1;\r
-       copy.source_handle = toxms? 0 : XMSHandle;\r
+       copy.source_handle = toxms? 0 : gvar->pm.xmm.XMSHandle;\r
        copy.source_offset = toxms? (long)addr : xoffset;\r
-       copy.target_handle = toxms? XMSHandle : 0;\r
+       copy.target_handle = toxms? gvar->pm.xmm.XMSHandle : 0;\r
        copy.target_offset = toxms? xoffset : (long)addr;\r
 \r
-asm    push si\r
+       __asm {\r
+               push si\r
+       }\r
        _SI = (word)&copy;\r
        XMS_CALL(XMS_MOVE);\r
-asm    pop     si\r
+       __asm {\r
+               pop     si\r
+       }\r
        if (!_AX)\r
+       {\r
                Quit("PML_XMSCopy: Error on copy");\r
+               //return;\r
+       }\r
 }\r
 \r
 #if 1\r
-#define        PML_CopyToXMS(s,t,l)    PML_XMSCopy(true,(s),(t),(l))\r
-#define        PML_CopyFromXMS(t,s,l)  PML_XMSCopy(false,(t),(s),(l))\r
+#define        PML_CopyToXMS(s,t,l,gvar)       PML_XMSCopy(true,(s),(t),(l),(gvar))\r
+#define        PML_CopyFromXMS(t,s,l,gvar)     PML_XMSCopy(false,(t),(s),(l),(gvar))\r
 #else\r
 //\r
 //     PML_CopyToXMS() - Copies the specified number of bytes from the real mode\r
 //             segment address to the specified XMS page\r
 //\r
 void\r
-PML_CopyToXMS(byte far *source,int targetpage,word length)\r
+PML_CopyToXMS(byte far *source,int targetpage,word length,global_game_variables_t *gvar)\r
 {\r
-       PML_XMSCopy(true,source,targetpage,length);\r
+       PML_XMSCopy(true,source,targetpage,length, global_game_variables_t *gvar);\r
 }\r
 \r
 //\r
@@ -295,9 +560,9 @@ PML_CopyToXMS(byte far *source,int targetpage,word length)
 //             page to the specified real mode address\r
 //\r
 void\r
-PML_CopyFromXMS(byte far *target,int sourcepage,word length)\r
+PML_CopyFromXMS(byte far *target,int sourcepage,word length, global_game_variables_t *gvar)\r
 {\r
-       PML_XMSCopy(false,target,sourcepage,length);\r
+       PML_XMSCopy(false,target,sourcepage,length, global_game_variables_t *gvar);\r
 }\r
 #endif\r
 \r
@@ -305,14 +570,42 @@ PML_CopyFromXMS(byte far *target,int sourcepage,word length)
 //     PML_ShutdownXMS()\r
 //\r
 void\r
-PML_ShutdownXMS(void)\r
+PML_ShutdownXMS(global_game_variables_t *gvar)\r
 {\r
-       if (XMSPresent)\r
+       boolean errorflag=false;\r
+       word XMSHandle = gvar->pm.xmm.XMSHandle;\r
+       if (gvar->pm.xmm.XMSPresent)\r
        {\r
-               _DX = XMSHandle;\r
-               XMS_CALL(XMS_FREE);\r
-               if (_BL)\r
+               __asm {\r
+                       mov     dx,[XMSHandle]\r
+                       //XMS_CALL(XMS_FREE);\r
+                       mov     ah,XMS_FREE\r
+                       call    [DWORD PTR XMSDriver]\r
+                       or      bl,bl\r
+                       jz      errorxs\r
+                       jmp     Endxs\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       errorxs:\r
+#ifdef __BORLANDC__\r
+               __asm {\r
+#endif\r
+                       //mov   err,ah\r
+                       mov     errorflag,1\r
+                       jmp     Endxs\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       Endxs:\r
+#ifdef __WATCOMC__\r
+               }\r
+#endif\r
+               if(errorflag==true)\r
+               {\r
                        Quit("PML_ShutdownXMS: Error freeing XMS");\r
+                       //return;\r
+               }\r
        }\r
 }\r
 \r
@@ -328,13 +621,25 @@ PML_ShutdownXMS(void)
 //             PM_UnlockMainMem() macros should be used instead.\r
 //\r
 void\r
-PM_SetMainMemPurge(int level)\r
+PM_SetMainMemPurge(int level, global_game_variables_t *gvar)\r
 {\r
        int     i;\r
 \r
+       if(gvar->pm.mm.MainPresent)\r
        for (i = 0;i < PMMaxMainMem;i++)\r
-               if (MainMemPages[i])\r
-                       MM_SetPurge(&MainMemPages[i],level);\r
+       {\r
+#ifdef __DEBUG_PM__\r
+               printf("PM_SetMainMemPurge()    info of gvar->pm.mm.MainMemPages[i]\n");\r
+               printf("&       %Fp,    %Fp\n", &gvar->pm.mm.MainMemPages[i],   &(gvar->pm.mm.MainMemPages[i]));\r
+#endif\r
+               if (gvar->pm.mm.MainMemPages[i])\r
+                       MM_SetPurge(&(gvar->pm.mm.MainMemPages[i]),level, gvar);\r
+       }\r
+\r
+       else\r
+       {\r
+               Quit("MainPresent IS NULL\n");\r
+       }\r
 }\r
 \r
 //\r
@@ -351,7 +656,7 @@ PM_SetMainMemPurge(int level)
 //             program makes allocation requests of the Memory Mgr.\r
 //\r
 void\r
-PM_CheckMainMem(void)\r
+PM_CheckMainMem(global_game_variables_t *gvar)\r
 {\r
        boolean                 allocfailed;\r
        int                             i,n;\r
@@ -359,15 +664,15 @@ PM_CheckMainMem(void)
        PMBlockAttr             *used;\r
        PageListStruct  far *page;\r
 \r
-       if (!MainPresent)\r
+       if (!gvar->pm.mm.MainPresent)\r
                return;\r
 \r
-       for (i = 0,page = PMPages;i < ChunksInFile;i++,page++)\r
+       for (i = 0,page = gvar->pm.PMPages;i < gvar->pm.fi.ChunksInFile;i++,page++)\r
        {\r
                n = page->mainPage;\r
                if (n != -1)                                            // Is the page using main memory?\r
                {\r
-                       if (!MainMemPages[n])                   // Yep, was the block purged?\r
+                       if (!gvar->pm.mm.MainMemPages[n])                       // Yep, was the block purged?\r
                        {\r
                                page->mainPage = -1;            // Yes, mark page as purged & unlocked\r
                                page->locked = pml_Unlocked;\r
@@ -376,41 +681,41 @@ PM_CheckMainMem(void)
        }\r
 \r
        // Prevent allocation attempts from purging any of our other blocks\r
-       PM_LockMainMem();\r
+       PM_LockMainMem(gvar);\r
        allocfailed = false;\r
-       for (i = 0,p = MainMemPages,used = MainMemUsed;i < PMMaxMainMem;i++,p++,used++)\r
+       for (i = 0,p = gvar->pm.mm.MainMemPages,used = gvar->pm.mm.MainMemUsed; i < PMMaxMainMem;i++,p++,used++)\r
        {\r
                if (!*p)                                                        // If the page got purged\r
                {\r
                        if (*used & pmba_Allocated)             // If it was allocated\r
                        {\r
                                *used &= ~pmba_Allocated;       // Mark as unallocated\r
-                               MainPagesAvail--;                       // and decrease available count\r
+                               gvar->pm.mm.MainPagesAvail--;                   // and decrease available count\r
                        }\r
 \r
                        if (*used & pmba_Used)                  // If it was used\r
                        {\r
                                *used &= ~pmba_Used;            // Mark as unused\r
-                               MainPagesUsed--;                        // and decrease used count\r
+                               gvar->pm.MainPagesUsed--;                       // and decrease used count\r
                        }\r
 \r
                        if (!allocfailed)\r
                        {\r
-                               MM_BombOnError(false);\r
-                               MM_GetPtr(p,PMPageSize);                // Try to reallocate\r
-                               if (mmerror)                                    // If it failed,\r
+                               MM_BombOnError(false, gvar);\r
+                               MM_GetPtr(p,PMPageSize, gvar);          // Try to reallocate\r
+                               if (gvar->mm.mmerror)                                   // If it failed,\r
                                        allocfailed = true;                     //  don't try any more allocations\r
                                else                                                    // If it worked,\r
                                {\r
                                        *used |= pmba_Allocated;        // Mark as allocated\r
-                                       MainPagesAvail++;                       // and increase available count\r
+                                       gvar->pm.mm.MainPagesAvail++;                   // and increase available count\r
                                }\r
-                               MM_BombOnError(true);\r
+                               MM_BombOnError(true, gvar);\r
                        }\r
                }\r
        }\r
-       if (mmerror)\r
-               mmerror = false;\r
+       if (gvar->mm.mmerror)\r
+               gvar->mm.mmerror = false;\r
 }\r
 \r
 //\r
@@ -420,28 +725,32 @@ PM_CheckMainMem(void)
 //             needs to be called.\r
 //\r
 void\r
-PML_StartupMainMem(void)\r
+PML_StartupMainMem(global_game_variables_t *gvar)\r
 {\r
        int             i,n;\r
        memptr  *p;\r
 \r
-       MainPagesAvail = 0;\r
-       MM_BombOnError(false);\r
-       for (i = 0,p = MainMemPages;i < PMMaxMainMem;i++,p++)\r
+       gvar->pm.mm.MainPagesAvail = 0;\r
+       gvar->pm.mm.MainPresent = false;\r
+       MM_BombOnError(false, gvar);\r
+       for (i = 0,p = gvar->pm.mm.MainMemPages;i < PMMaxMainMem;i++,p++)\r
        {\r
-               MM_GetPtr(p,PMPageSize);\r
-               if (mmerror)\r
+               MM_GetPtr(p,PMPageSize, gvar);\r
+               if (gvar->mm.mmerror)\r
                        break;\r
 \r
-               MainPagesAvail++;\r
-               MainMemUsed[i] = pmba_Allocated;\r
+               gvar->pm.mm.MainPagesAvail++;\r
+               gvar->pm.mm.MainMemUsed[i] = pmba_Allocated;\r
        }\r
-       MM_BombOnError(true);\r
-       if (mmerror)\r
-               mmerror = false;\r
-       if (MainPagesAvail < PMMinMainMem)\r
+       MM_BombOnError(true, gvar);\r
+       if (gvar->mm.mmerror)\r
+               gvar->mm.mmerror = false;\r
+       if (gvar->pm.mm.MainPagesAvail < PMMinMainMem)\r
+       {\r
                Quit("PM_SetupMainMem: Not enough main memory");\r
-       MainPresent = true;\r
+               //return;\r
+       }\r
+       gvar->pm.mm.MainPresent = true;\r
 }\r
 \r
 //\r
@@ -449,15 +758,15 @@ PML_StartupMainMem(void)
 //             Page Mgr.\r
 //\r
 void\r
-PML_ShutdownMainMem(void)\r
+PML_ShutdownMainMem(global_game_variables_t *gvar)\r
 {\r
        int             i;\r
        memptr  *p;\r
 \r
        // DEBUG - mark pages as unallocated & decrease page count as appropriate\r
-       for (i = 0,p = MainMemPages;i < PMMaxMainMem;i++,p++)\r
+       for (i = 0,p = gvar->pm.mm.MainMemPages;i < PMMaxMainMem;i++,p++)\r
                if (*p)\r
-                       MM_FreePtr(p);\r
+                       MM_FreePtr(p, gvar);\r
 }\r
 \r
 /////////////////////////////////////////////////////////////////////////////\r
@@ -470,80 +779,102 @@ PML_ShutdownMainMem(void)
 //     PML_ReadFromFile() - Reads some data in from the page file\r
 //\r
 void\r
-PML_ReadFromFile(byte far *buf,long offset,word length)\r
+PML_ReadFromFile(byte far *buf,long offset,word length, global_game_variables_t *gvar)\r
 {\r
        if (!buf)\r
+       {\r
                Quit("PML_ReadFromFile: Null pointer");\r
+               //return;\r
+       }\r
        if (!offset)\r
+       {\r
                Quit("PML_ReadFromFile: Zero offset");\r
-       if (lseek(PageFile,offset,SEEK_SET) != offset)\r
+               //return;\r
+       }\r
+       if (lseek(gvar->pm.fi.PageFile,offset,SEEK_SET) != offset)\r
+       {\r
                Quit("PML_ReadFromFile: Seek failed");\r
-       if (!CA_FarRead(PageFile,buf,length))\r
+               //return;\r
+       }\r
+       if (!CA_FarRead(gvar->pm.fi.PageFile,buf,length, gvar))\r
+       {\r
                Quit("PML_ReadFromFile: Read failed");\r
+               //return;\r
+       }\r
 }\r
 \r
 //\r
 //     PML_OpenPageFile() - Opens the page file and sets up the page info\r
 //\r
 void\r
-PML_OpenPageFile(void)\r
+PML_OpenPageFile(global_game_variables_t *gvar)\r
 {\r
        int                             i;\r
        long                    size;\r
-       void                    _seg *buf;\r
-       longword                far *offsetptr;\r
+                               //__SEGA buf;\r
+       memptr          buf;\r
+       dword           far *offsetptr;\r
        word                    far *lengthptr;\r
        PageListStruct  far *page;\r
 \r
-       PageFile = open(PageFileName,O_RDONLY + O_BINARY);\r
-       if (PageFile == -1)\r
+       gvar->pm.fi.PageFile = open(gvar->pm.fi.PageFileName,O_RDONLY + O_BINARY);\r
+       if (gvar->pm.fi.PageFile == -1)\r
+       {\r
                Quit("PML_OpenPageFile: Unable to open page file");\r
+               //return;\r
+       }\r
 \r
        // Read in header variables\r
-       read(PageFile,&ChunksInFile,sizeof(ChunksInFile));\r
-       read(PageFile,&PMSpriteStart,sizeof(PMSpriteStart));\r
-       read(PageFile,&PMSoundStart,sizeof(PMSoundStart));\r
+       read(gvar->pm.fi.PageFile,&gvar->pm.fi.ChunksInFile,sizeof(gvar->pm.fi.ChunksInFile));\r
+       read(gvar->pm.fi.PageFile,&gvar->pm.fi.PMSpriteStart,sizeof(gvar->pm.fi.PMSpriteStart));\r
+       read(gvar->pm.fi.PageFile,&gvar->pm.fi.PMSoundStart,sizeof(gvar->pm.fi.PMSoundStart));\r
 \r
        // Allocate and clear the page list\r
-       PMNumBlocks = ChunksInFile;\r
-       MM_GetPtr(&(memptr)PMSegPages,sizeof(PageListStruct) * PMNumBlocks);\r
-       MM_SetLock(&(memptr)PMSegPages,true);\r
-       PMPages = (PageListStruct far *)PMSegPages;\r
-       _fmemset(PMPages,0,sizeof(PageListStruct) * PMNumBlocks);\r
+       gvar->pm.PMNumBlocks = gvar->pm.fi.ChunksInFile;\r
+       MM_GetPtr((memptr *)gvar->pm.PMSegPages, sizeof(PageListStruct) * (gvar->pm.PMNumBlocks), gvar);\r
+       MM_SetLock((memptr *)gvar->pm.PMSegPages,true, gvar);\r
+       gvar->pm.PMPages = (PageListStruct far *)gvar->pm.PMSegPages;\r
+       _fmemset(gvar->pm.PMPages,0,sizeof(PageListStruct) * gvar->pm.PMNumBlocks);\r
 \r
        // Read in the chunk offsets\r
-       size = sizeof(longword) * ChunksInFile;\r
-       MM_GetPtr(&buf,size);\r
-       if (!CA_FarRead(PageFile,(byte far *)buf,size))\r
+       size = sizeof(dword) * gvar->pm.fi.ChunksInFile;\r
+       MM_GetPtr(&buf, size, gvar);\r
+       if (!CA_FarRead(gvar->pm.fi.PageFile,(byte far *)buf,size, gvar))\r
+       {\r
                Quit("PML_OpenPageFile: Offset read failed");\r
-       offsetptr = (longword far *)buf;\r
-       for (i = 0,page = PMPages;i < ChunksInFile;i++,page++)\r
+               //return;\r
+       }\r
+       offsetptr = (dword far *)buf;\r
+       for (i = 0,page = gvar->pm.PMPages;i < gvar->pm.fi.ChunksInFile;i++,page++)\r
                page->offset = *offsetptr++;\r
-       MM_FreePtr(&buf);\r
+       MM_FreePtr(&buf, gvar);\r
 \r
        // Read in the chunk lengths\r
-       size = sizeof(word) * ChunksInFile;\r
-       MM_GetPtr(&buf,size);\r
-       if (!CA_FarRead(PageFile,(byte far *)buf,size))\r
+       size = sizeof(word) * gvar->pm.fi.ChunksInFile;\r
+       MM_GetPtr(&buf,size, gvar);\r
+       if (!CA_FarRead(gvar->pm.fi.PageFile,(byte far *)buf,size, gvar))\r
+       {\r
                Quit("PML_OpenPageFile: Length read failed");\r
+               //return;\r
+       }\r
        lengthptr = (word far *)buf;\r
-       for (i = 0,page = PMPages;i < ChunksInFile;i++,page++)\r
+       for (i = 0,page = gvar->pm.PMPages;i < gvar->pm.fi.ChunksInFile;i++,page++)\r
                page->length = *lengthptr++;\r
-       MM_FreePtr(&buf);\r
+       MM_FreePtr(&buf, gvar);\r
 }\r
 \r
 //\r
 //  PML_ClosePageFile() - Closes the page file\r
 //\r
 void\r
-PML_ClosePageFile(void)\r
+PML_ClosePageFile(global_game_variables_t *gvar)\r
 {\r
-       if (PageFile != -1)\r
-               close(PageFile);\r
-       if (PMSegPages)\r
+       if (gvar->pm.fi.PageFile != -1)\r
+               close(gvar->pm.fi.PageFile);\r
+       if (gvar->pm.PMSegPages)\r
        {\r
-               MM_SetLock(&(memptr)PMSegPages,false);\r
-               MM_FreePtr(&(void _seg *)PMSegPages);\r
+               MM_SetLock((memptr)gvar->pm.PMSegPages,false, gvar);\r
+               MM_FreePtr((memptr)gvar->pm.PMSegPages, gvar);\r
        }\r
 }\r
 \r
@@ -560,10 +891,10 @@ PML_ClosePageFile(void)
 //             to map our page in. If normal page, use EMS physical page 3, else\r
 //             use the physical page specified by the lock type\r
 //\r
-#if 1\r
+#ifndef __DEBUG_2__\r
 #pragma argsused       // DEBUG - remove lock parameter\r
 memptr\r
-PML_GetEMSAddress(int page,PMLockType lock)\r
+PML_GetEMSAddress(int page,PMLockType lock, global_game_variables_t *gvar)\r
 {\r
        int             i,emspage;\r
        word    emsoff,emsbase,offset;\r
@@ -575,7 +906,7 @@ PML_GetEMSAddress(int page,PMLockType lock)
        // See if this page is already mapped in\r
        for (i = 0;i < EMSFrameCount;i++)\r
        {\r
-               if (EMSList[i].baseEMSPage == emsbase)\r
+               if (gvar->pm.emm.EMSList[i].baseEMSPage == emsbase)\r
                {\r
                        emspage = i;    // Yep - don't do a redundant remapping\r
                        break;\r
@@ -585,31 +916,31 @@ PML_GetEMSAddress(int page,PMLockType lock)
        // If page isn't already mapped in, find LRU EMS frame, and use it\r
        if (emspage == -1)\r
        {\r
-               longword last = MAXLONG;\r
+               dword last = LONG_MAX;\r
                for (i = 0;i < EMSFrameCount;i++)\r
                {\r
-                       if (EMSList[i].lastHit < last)\r
+                       if (gvar->pm.emm.EMSList[i].lastHit < last)\r
                        {\r
                                emspage = i;\r
-                               last = EMSList[i].lastHit;\r
+                               last = gvar->pm.emm.EMSList[i].lastHit;\r
                        }\r
                }\r
 \r
-               EMSList[emspage].baseEMSPage = emsbase;\r
-               PML_MapEMS(page / PMEMSSubPage,emspage);\r
+               gvar->pm.emm.EMSList[emspage].baseEMSPage = emsbase;\r
+               PML_MapEMS(page / PMEMSSubPage,emspage, gvar);\r
        }\r
 \r
        if (emspage == -1)\r
                Quit("PML_GetEMSAddress: EMS find failed");\r
 \r
-       EMSList[emspage].lastHit = PMFrameCount;\r
+       gvar->pm.emm.EMSList[emspage].lastHit = gvar->pm.PMFrameCount;\r
        offset = emspage * EMSPageSizeSeg;\r
        offset += emsoff * PMPageSizeSeg;\r
-       return((memptr)(EMSPageFrame + offset));\r
+       return((memptr)(gvar->pm.emm.EMSPageFrame + offset));\r
 }\r
 #else\r
 memptr\r
-PML_GetEMSAddress(int page,PMLockType lock)\r
+PML_GetEMSAddress(int page,PMLockType lock, global_game_variables_t *gvar)\r
 {\r
        word    emspage;\r
 \r
@@ -629,15 +960,15 @@ PML_GetEMSAddress(int page,PMLockType lock)
 //\r
 //\r
 memptr\r
-PM_GetPageAddress(int pagenum)\r
+PM_GetPageAddress(int pagenum, global_game_variables_t *gvar)\r
 {\r
        PageListStruct  far *page;\r
 \r
-       page = &PMPages[pagenum];\r
+       page = &gvar->pm.PMPages[pagenum];\r
        if (page->mainPage != -1)\r
-               return(MainMemPages[page->mainPage]);\r
+               return(gvar->pm.mm.MainMemPages[page->mainPage]);\r
        else if (page->emsPage != -1)\r
-               return(PML_GetEMSAddress(page->emsPage,page->locked));\r
+               return(PML_GetEMSAddress(page->emsPage,page->locked, gvar));\r
        else\r
                return(nil);\r
 }\r
@@ -647,13 +978,13 @@ PM_GetPageAddress(int pagenum)
 //             present & unlocked main/EMS page (or main page if mainonly is true)\r
 //\r
 int\r
-PML_GiveLRUPage(boolean mainonly)\r
+PML_GiveLRUPage(boolean mainonly, global_game_variables_t *gvar)\r
 {\r
        int                             i,lru;\r
        long                    last;\r
        PageListStruct  far *page;\r
 \r
-       for (i = 0,page = PMPages,lru = -1,last = MAXLONG;i < ChunksInFile;i++,page++)\r
+       for (i = 0,page = gvar->pm.PMPages,lru = -1,last = LONG_MAX;i < gvar->pm.fi.ChunksInFile;i++,page++)\r
        {\r
                if\r
                (\r
@@ -679,19 +1010,19 @@ PML_GiveLRUPage(boolean mainonly)
 //     This routine won't return the XMS page protected (by XMSProtectPage)\r
 //\r
 int\r
-PML_GiveLRUXMSPage(void)\r
+PML_GiveLRUXMSPage(global_game_variables_t *gvar)\r
 {\r
        int                             i,lru;\r
        long                    last;\r
        PageListStruct  far *page;\r
 \r
-       for (i = 0,page = PMPages,lru = -1,last = MAXLONG;i < ChunksInFile;i++,page++)\r
+       for (i = 0,page = gvar->pm.PMPages,lru = -1,last = LONG_MAX;i < gvar->pm.fi.ChunksInFile;i++,page++)\r
        {\r
                if\r
                (\r
                        (page->xmsPage != -1)\r
                &&      (page->lastHit < last)\r
-               &&      (i != XMSProtectPage)\r
+               &&      (i != gvar->pm.xmm.XMSProtectPage)\r
                )\r
                {\r
                        last = page->lastHit;\r
@@ -706,29 +1037,29 @@ PML_GiveLRUXMSPage(void)
 //             it with the main/EMS page\r
 //\r
 void\r
-PML_PutPageInXMS(int pagenum)\r
+PML_PutPageInXMS(int pagenum, global_game_variables_t *gvar)\r
 {\r
        int                             usexms;\r
        PageListStruct  far *page;\r
 \r
-       if (!XMSPresent)\r
+       if (!gvar->pm.xmm.XMSPresent)\r
                return;\r
 \r
-       page = &PMPages[pagenum];\r
+       page = &gvar->pm.PMPages[pagenum];\r
        if (page->xmsPage != -1)\r
                return;                                 // Already in XMS\r
 \r
-       if (XMSPagesUsed < XMSPagesAvail)\r
-               page->xmsPage = XMSPagesUsed++;\r
+       if (gvar->pm.XMSPagesUsed < gvar->pm.xmm.XMSPagesAvail)\r
+               page->xmsPage = gvar->pm.XMSPagesUsed++;\r
        else\r
        {\r
-               usexms = PML_GiveLRUXMSPage();\r
+               usexms = PML_GiveLRUXMSPage(gvar);\r
                if (usexms == -1)\r
                        Quit("PML_PutPageInXMS: No XMS LRU");\r
-               page->xmsPage = PMPages[usexms].xmsPage;\r
-               PMPages[usexms].xmsPage = -1;\r
+               page->xmsPage = gvar->pm.PMPages[usexms].xmsPage;\r
+               gvar->pm.PMPages[usexms].xmsPage = -1;\r
        }\r
-       PML_CopyToXMS(PM_GetPageAddress(pagenum),page->xmsPage,page->length);\r
+       PML_CopyToXMS(PM_GetPageAddress(pagenum, gvar),page->xmsPage,page->length, gvar);\r
 }\r
 \r
 //\r
@@ -736,7 +1067,7 @@ PML_PutPageInXMS(int pagenum)
 //             the old one's address space. Returns the address of the new page.\r
 //\r
 memptr\r
-PML_TransferPageSpace(int orig,int new)\r
+PML_TransferPageSpace(int orig,int new, global_game_variables_t *gvar)\r
 {\r
        memptr                  addr;\r
        PageListStruct  far *origpage,far *newpage;\r
@@ -744,8 +1075,8 @@ PML_TransferPageSpace(int orig,int new)
        if (orig == new)\r
                Quit("PML_TransferPageSpace: Identity replacement");\r
 \r
-       origpage = &PMPages[orig];\r
-       newpage = &PMPages[new];\r
+       origpage = &gvar->pm.PMPages[orig];\r
+       newpage = &gvar->pm.PMPages[new];\r
 \r
        if (origpage->locked != pml_Unlocked)\r
                Quit("PML_TransferPageSpace: Killing locked page");\r
@@ -754,10 +1085,10 @@ PML_TransferPageSpace(int orig,int new)
                Quit("PML_TransferPageSpace: Reusing non-existent page");\r
 \r
        // Copy page that's about to be purged into XMS\r
-       PML_PutPageInXMS(orig);\r
+       PML_PutPageInXMS(orig, gvar);\r
 \r
        // Get the address, and force EMS into a physical page if necessary\r
-       addr = PM_GetPageAddress(orig);\r
+       addr = PM_GetPageAddress(orig, gvar);\r
 \r
        // Steal the address\r
        newpage->emsPage = origpage->emsPage;\r
@@ -781,24 +1112,24 @@ PML_TransferPageSpace(int orig,int new)
 //             will be looked at by PML_GiveLRUPage().\r
 //\r
 byte far *\r
-PML_GetAPageBuffer(int pagenum,boolean mainonly)\r
+PML_GetAPageBuffer(int pagenum,boolean mainonly, global_game_variables_t *gvar)\r
 {\r
        byte                    far *addr = nil;\r
        int                             i,n;\r
        PMBlockAttr             *used;\r
        PageListStruct  far *page;\r
 \r
-       page = &PMPages[pagenum];\r
-       if ((EMSPagesUsed < EMSPagesAvail) && !mainonly)\r
+       page = &gvar->pm.PMPages[pagenum];\r
+       if ((gvar->pm.EMSPagesUsed < gvar->pm.emm.EMSPagesAvail) && !mainonly)\r
        {\r
                // There's remaining EMS - use it\r
-               page->emsPage = EMSPagesUsed++;\r
-               addr = PML_GetEMSAddress(page->emsPage,page->locked);\r
+               page->emsPage = gvar->pm.EMSPagesUsed++;\r
+               addr = PML_GetEMSAddress(page->emsPage,page->locked, gvar);\r
        }\r
-       else if (MainPagesUsed < MainPagesAvail)\r
+       else if (gvar->pm.MainPagesUsed < gvar->pm.mm.MainPagesAvail)\r
        {\r
                // There's remaining main memory - use it\r
-               for (i = 0,n = -1,used = MainMemUsed;i < PMMaxMainMem;i++,used++)\r
+               for (i = 0,n = -1,used = gvar->pm.mm.MainMemUsed;i < PMMaxMainMem;i++,used++)\r
                {\r
                        if ((*used & pmba_Allocated) && !(*used & pmba_Used))\r
                        {\r
@@ -809,14 +1140,14 @@ PML_GetAPageBuffer(int pagenum,boolean mainonly)
                }\r
                if (n == -1)\r
                        Quit("PML_GetPageBuffer: MainPagesAvail lied");\r
-               addr = MainMemPages[n];\r
+               addr = gvar->pm.mm.MainMemPages[n];\r
                if (!addr)\r
                        Quit("PML_GetPageBuffer: Purged main block");\r
                page->mainPage = n;\r
-               MainPagesUsed++;\r
+               gvar->pm.MainPagesUsed++;\r
        }\r
        else\r
-               addr = PML_TransferPageSpace(PML_GiveLRUPage(mainonly),pagenum);\r
+               addr = PML_TransferPageSpace(PML_GiveLRUPage(mainonly, gvar),pagenum, gvar);\r
 \r
        if (!addr)\r
                Quit("PML_GetPageBuffer: Search failed");\r
@@ -833,22 +1164,22 @@ PML_GetAPageBuffer(int pagenum,boolean mainonly)
 //             (pages that are being purged are copied into XMS, if possible)\r
 //\r
 memptr\r
-PML_GetPageFromXMS(int pagenum,boolean mainonly)\r
+PML_GetPageFromXMS(int pagenum,boolean mainonly, global_game_variables_t *gvar)\r
 {\r
        byte                    far *checkaddr;\r
        memptr                  addr = nil;\r
        PageListStruct  far *page;\r
 \r
-       page = &PMPages[pagenum];\r
-       if (XMSPresent && (page->xmsPage != -1))\r
+       page = &gvar->pm.PMPages[pagenum];\r
+       if (gvar->pm.xmm.XMSPresent && (page->xmsPage != -1))\r
        {\r
-               XMSProtectPage = pagenum;\r
-               checkaddr = PML_GetAPageBuffer(pagenum,mainonly);\r
+               gvar->pm.xmm.XMSProtectPage = pagenum;\r
+               checkaddr = PML_GetAPageBuffer(pagenum,mainonly, gvar);\r
                if (FP_OFF(checkaddr))\r
                        Quit("PML_GetPageFromXMS: Non segment pointer");\r
                addr = (memptr)FP_SEG(checkaddr);\r
-               PML_CopyFromXMS(addr,page->xmsPage,page->length);\r
-               XMSProtectPage = -1;\r
+               PML_CopyFromXMS(addr,page->xmsPage,page->length, gvar);\r
+               gvar->pm.xmm.XMSProtectPage = -1;\r
        }\r
 \r
        return(addr);\r
@@ -860,14 +1191,14 @@ PML_GetPageFromXMS(int pagenum,boolean mainonly)
 //             only be loaded into main.\r
 //\r
 void\r
-PML_LoadPage(int pagenum,boolean mainonly)\r
+PML_LoadPage(int pagenum,boolean mainonly, global_game_variables_t *gvar)\r
 {\r
        byte                    far *addr;\r
        PageListStruct  far *page;\r
 \r
-       addr = PML_GetAPageBuffer(pagenum,mainonly);\r
-       page = &PMPages[pagenum];\r
-       PML_ReadFromFile(addr,page->offset,page->length);\r
+       addr = PML_GetAPageBuffer(pagenum,mainonly, gvar);\r
+       page = &gvar->pm.PMPages[pagenum];\r
+       PML_ReadFromFile(addr,page->offset,page->length, gvar);\r
 }\r
 \r
 //\r
@@ -878,49 +1209,52 @@ PML_LoadPage(int pagenum,boolean mainonly)
 //\r
 #pragma warn -pia\r
 memptr\r
-PM_GetPage(int pagenum)\r
+PM_GetPage(int pagenum, global_game_variables_t *gvar)\r
 {\r
        memptr  result;\r
 \r
-       if (pagenum >= ChunksInFile)\r
+       if (pagenum >= gvar->pm.fi.ChunksInFile)\r
                Quit("PM_GetPage: Invalid page request");\r
 \r
-#if 0  // for debugging\r
-asm    mov     dx,STATUS_REGISTER_1\r
-asm    in      al,dx\r
-asm    mov     dx,ATR_INDEX\r
-asm    mov     al,ATR_OVERSCAN\r
-asm    out     dx,al\r
-asm    mov     al,10   // bright green\r
-asm    out     dx,al\r
+#ifdef __DEBUG_2__     // for debugging\r
+       __asm {\r
+               mov     dx,STATUS_REGISTER_1\r
+               in      al,dx\r
+               mov     dx,ATR_INDEX\r
+               mov     al,ATR_OVERSCAN\r
+               out     dx,al\r
+               mov     al,10   // bright green\r
+               out     dx,al\r
+       }\r
 #endif\r
 \r
-       if (!(result = PM_GetPageAddress(pagenum)))\r
+       if (!(result = PM_GetPageAddress(pagenum, gvar)))\r
        {\r
-               boolean mainonly = (pagenum >= PMSoundStart);\r
-if (!PMPages[pagenum].offset)  // JDC: sparse page\r
+               boolean mainonly = (pagenum >= gvar->pm.fi.PMSoundStart);\r
+if (!gvar->pm.PMPages[pagenum].offset) // JDC: sparse page\r
        Quit ("Tried to load a sparse page!");\r
-               if (!(result = PML_GetPageFromXMS(pagenum,mainonly)))\r
+               if (!(result = PML_GetPageFromXMS(pagenum,mainonly, gvar)))\r
                {\r
-                       if (PMPages[pagenum].lastHit == PMFrameCount)\r
-                               PMThrashing++;\r
+                       if (gvar->pm.PMPages[pagenum].lastHit ==  gvar->pm.PMFrameCount)\r
+                               gvar->pm.PMThrashing++;\r
 \r
-                       PML_LoadPage(pagenum,mainonly);\r
-                       result = PM_GetPageAddress(pagenum);\r
+                       PML_LoadPage(pagenum,mainonly, gvar);\r
+                       result = PM_GetPageAddress(pagenum, gvar);\r
                }\r
        }\r
-       PMPages[pagenum].lastHit = PMFrameCount;\r
-\r
-#if 0  // for debugging\r
-asm    mov     dx,STATUS_REGISTER_1\r
-asm    in      al,dx\r
-asm    mov     dx,ATR_INDEX\r
-asm    mov     al,ATR_OVERSCAN\r
-asm    out     dx,al\r
-asm    mov     al,3    // blue\r
-asm    out     dx,al\r
-asm    mov     al,0x20 // normal\r
-asm    out     dx,al\r
+       gvar->pm.PMPages[pagenum].lastHit =  gvar->pm.PMFrameCount;\r
+\r
+#ifdef __DEBUG_2__     // for debugging\r
+       __asm{\r
+               mov     dx,STATUS_REGISTER_1\r
+               in      al,dx\r
+               mov     dx,ATR_INDEX\r
+               mov     al,ATR_OVERSCAN\r
+               out     dx,al\r
+               mov     al,3    // blue\r
+               out     dx,al\r
+               mov     al,0x20 // normal\r
+               out     dx,al\r
 #endif\r
 \r
        return(result);\r
@@ -935,12 +1269,12 @@ asm      out     dx,al
 //                                     specified when returning the address. For sound stuff.\r
 //\r
 void\r
-PM_SetPageLock(int pagenum,PMLockType lock)\r
+PM_SetPageLock(int pagenum,PMLockType lock, global_game_variables_t *gvar)\r
 {\r
-       if (pagenum < PMSoundStart)\r
+       if (pagenum < gvar->pm.fi.PMSoundStart)\r
                Quit("PM_SetPageLock: Locking/unlocking non-sound page");\r
 \r
-       PMPages[pagenum].locked = lock;\r
+       gvar->pm.PMPages[pagenum].locked = lock;\r
 }\r
 \r
 //\r
@@ -949,7 +1283,7 @@ PM_SetPageLock(int pagenum,PMLockType lock)
 //             page, and the total pages that need to be loaded (for thermometer).\r
 //\r
 void\r
-PM_Preload(boolean (*update)(word current,word total))\r
+PM_Preload(boolean (*update)(word current,word total), global_game_variables_t *gvar)\r
 {\r
        int                             i,j,\r
                                        page,oogypage;\r
@@ -961,17 +1295,17 @@ PM_Preload(boolean (*update)(word current,word total))
        memptr                  addr;\r
        PageListStruct  far *p;\r
 \r
-       mainfree = (MainPagesAvail - MainPagesUsed) + (EMSPagesAvail - EMSPagesUsed);\r
-       xmsfree = (XMSPagesAvail - XMSPagesUsed);\r
+       mainfree = (gvar->pm.mm.MainPagesAvail - gvar->pm.MainPagesUsed) + (gvar->pm.emm.EMSPagesAvail - gvar->pm.EMSPagesUsed);\r
+       xmsfree = (gvar->pm.xmm.XMSPagesAvail - gvar->pm.XMSPagesUsed);\r
 \r
        xmstotal = maintotal = 0;\r
 \r
-       for (i = 0;i < ChunksInFile;i++)\r
+       for (i = 0;i < gvar->pm.fi.ChunksInFile;i++)\r
        {\r
-               if (!PMPages[i].offset)\r
+               if (!gvar->pm.PMPages[i].offset)\r
                        continue;                       // sparse\r
 \r
-               if ( PMPages[i].emsPage != -1 || PMPages[i].mainPage != -1 )\r
+               if ( gvar->pm.PMPages[i].emsPage != -1 || gvar->pm.PMPages[i].mainPage != -1 )\r
                        continue;                       // already in main mem\r
 \r
                if ( mainfree )\r
@@ -979,7 +1313,7 @@ PM_Preload(boolean (*update)(word current,word total))
                        maintotal++;\r
                        mainfree--;\r
                }\r
-               else if ( xmsfree && (PMPages[i].xmsPage == -1) )\r
+               else if ( xmsfree && (gvar->pm.PMPages[i].xmsPage == -1) )\r
                {\r
                        xmstotal++;\r
                        xmsfree--;\r
@@ -1000,14 +1334,14 @@ PM_Preload(boolean (*update)(word current,word total))
 //\r
        while (maintotal)\r
        {\r
-               while ( !PMPages[page].offset || PMPages[page].mainPage != -1\r
-                       ||      PMPages[page].emsPage != -1 )\r
+               while ( !gvar->pm.PMPages[page].offset || gvar->pm.PMPages[page].mainPage != -1\r
+                       ||      gvar->pm.PMPages[page].emsPage != -1 )\r
                        page++;\r
 \r
-               if (page >= ChunksInFile)\r
-                       Quit ("PM_Preload: Pages>=ChunksInFile");\r
+               if (page >= gvar->pm.fi.ChunksInFile)\r
+                       Quit ("PM_Preload: Pages>=gvar->pm.fi.ChunksInFile");\r
 \r
-               PM_GetPage(page);\r
+               PM_GetPage(page, gvar);\r
 \r
                page++;\r
                current++;\r
@@ -1020,30 +1354,30 @@ PM_Preload(boolean (*update)(word current,word total))
 //\r
        if (xmstotal)\r
        {\r
-               for (oogypage = 0 ; PMPages[oogypage].mainPage == -1 ; oogypage++)\r
+               for (oogypage = 0 ; gvar->pm.PMPages[oogypage].mainPage == -1 ; oogypage++)\r
                ;\r
-               addr = PM_GetPage(oogypage);\r
+               addr = PM_GetPage(oogypage, gvar);\r
                if (!addr)\r
                        Quit("PM_Preload: XMS buffer failed");\r
 \r
                while (xmstotal)\r
                {\r
-                       while ( !PMPages[page].offset || PMPages[page].xmsPage != -1 )\r
+                       while ( !gvar->pm.PMPages[page].offset || gvar->pm.PMPages[page].xmsPage != -1 )\r
                                page++;\r
 \r
-                       if (page >= ChunksInFile)\r
-                               Quit ("PM_Preload: Pages>=ChunksInFile");\r
+                       if (page >= gvar->pm.fi.ChunksInFile)\r
+                               Quit ("PM_Preload: Pages>=gvar->pm.fi.ChunksInFile");\r
 \r
-                       p = &PMPages[page];\r
+                       p = &gvar->pm.PMPages[page];\r
 \r
-                       p->xmsPage = XMSPagesUsed++;\r
-                       if (XMSPagesUsed > XMSPagesAvail)\r
+                       p->xmsPage = gvar->pm.XMSPagesUsed++;\r
+                       if (gvar->pm.XMSPagesUsed > gvar->pm.xmm.XMSPagesAvail)\r
                                Quit("PM_Preload: Exceeded XMS pages");\r
                        if (p->length > PMPageSize)\r
                                Quit("PM_Preload: Page too long");\r
 \r
-                       PML_ReadFromFile((byte far *)addr,p->offset,p->length);\r
-                       PML_CopyToXMS((byte far *)addr,p->xmsPage,p->length);\r
+                       PML_ReadFromFile((byte far *)addr,p->offset,p->length, gvar);\r
+                       PML_CopyToXMS((byte far *)addr,p->xmsPage,p->length, gvar);\r
 \r
                        page++;\r
                        current++;\r
@@ -1051,8 +1385,8 @@ PM_Preload(boolean (*update)(word current,word total))
                        update(current,total);\r
                }\r
 \r
-               p = &PMPages[oogypage];\r
-               PML_ReadFromFile((byte far *)addr,p->offset,p->length);\r
+               p = &gvar->pm.PMPages[oogypage];\r
+               PML_ReadFromFile((byte far *)addr,p->offset,p->length, gvar);\r
        }\r
 \r
        update(total,total);\r
@@ -1074,63 +1408,66 @@ PM_Preload(boolean (*update)(word current,word total))
 //\r
 //\r
 void\r
-PM_NextFrame(void)\r
+PM_NextFrame(global_game_variables_t *gvar)\r
 {\r
        int     i;\r
 \r
        // Frame count overrun - kill the LRU hit entries & reset frame count\r
-       if (++PMFrameCount >= MAXLONG - 4)\r
+       if (++gvar->pm.PMFrameCount >= LONG_MAX - 4)\r
        {\r
-               for (i = 0;i < PMNumBlocks;i++)\r
-                       PMPages[i].lastHit = 0;\r
-               PMFrameCount = 0;\r
+               for (i = 0;i < gvar->pm.PMNumBlocks;i++)\r
+                       gvar->pm.PMPages[i].lastHit = 0;\r
+               gvar->pm.PMFrameCount = 0;\r
        }\r
 \r
-#if 0\r
-       for (i = 0;i < PMSoundStart;i++)\r
+//#if 0\r
+       for (i = 0;i < gvar->pm.fi.PMSoundStart;i++)\r
        {\r
-               if (PMPages[i].locked)\r
+               if (gvar->pm.PMPages[i].locked)\r
                {\r
                        char buf[40];\r
                        sprintf(buf,"PM_NextFrame: Page %d is locked",i);\r
                        Quit(buf);\r
                }\r
        }\r
-#endif\r
+//#endif\r
 \r
-       if (PMPanicMode)\r
+       if (gvar->pm.PMPanicMode)\r
        {\r
                // DEBUG - set border color\r
-               if ((!PMThrashing) && (!--PMPanicMode))\r
+               if ((!gvar->pm.PMThrashing) && (!--gvar->pm.PMPanicMode))\r
                {\r
                        // DEBUG - reset border color\r
                }\r
        }\r
-       if (PMThrashing >= PMThrashThreshold)\r
-               PMPanicMode = PMUnThrashThreshold;\r
-       PMThrashing = false;\r
+       if (gvar->pm.PMThrashing >= PMThrashThreshold)\r
+               gvar->pm.PMPanicMode = PMUnThrashThreshold;\r
+       gvar->pm.PMThrashing = false;\r
 }\r
 \r
 //\r
 //     PM_Reset() - Sets up caching structures\r
 //\r
 void\r
-PM_Reset(void)\r
+PM_Reset(global_game_variables_t *gvar)\r
 {\r
        int                             i;\r
        PageListStruct  far *page;\r
 \r
-       XMSPagesAvail = XMSAvail / PMPageSizeKB;\r
+       gvar->pm.xmm.XMSPagesAvail = gvar->pm.xmm.XMSAvail / PMPageSizeKB;\r
+\r
+       gvar->pm.emm.EMSPagesAvail = gvar->pm.emm.EMSAvail * (EMSPageSizeKB / PMPageSizeKB);\r
+       gvar->pm.emm.EMSPhysicalPage = 0;\r
 \r
-       EMSPagesAvail = EMSAvail * (EMSPageSizeKB / PMPageSizeKB);\r
-       EMSPhysicalPage = 0;\r
+       gvar->pm.MainPagesUsed = gvar->pm.EMSPagesUsed = gvar->pm.XMSPagesUsed = 0;\r
 \r
-       MainPagesUsed = EMSPagesUsed = XMSPagesUsed = 0;\r
+       gvar->pm.PMPanicMode = false;\r
 \r
-       PMPanicMode = false;\r
+       gvar->pm.fi.PageFile = -1;\r
+       gvar->pm.xmm.XMSProtectPage = -1;\r
 \r
        // Initialize page list\r
-       for (i = 0,page = PMPages;i < PMNumBlocks;i++,page++)\r
+       for (i = 0,page = gvar->pm.PMPages;i < gvar->pm.PMNumBlocks;i++,page++)\r
        {\r
                page->mainPage = -1;\r
                page->emsPage = -1;\r
@@ -1143,14 +1480,16 @@ PM_Reset(void)
 //     PM_Startup() - Start up the Page Mgr\r
 //\r
 void\r
-PM_Startup(void)\r
+PM_Startup(global_game_variables_t *gvar)\r
 {\r
        boolean nomain,noems,noxms;\r
        int             i;\r
 \r
-       if (PMStarted)\r
+       if (gvar->pm.PMStarted)\r
                return;\r
 \r
+       //strcpy(&(gvar->pm.fi.PageFileName), "VSWAP.");\r
+\r
        nomain = noems = noxms = false;\r
        for (i = 1;i < _argc;i++)\r
        {\r
@@ -1168,39 +1507,39 @@ PM_Startup(void)
                }\r
        }\r
 \r
-       PML_OpenPageFile();\r
+       //0000+=+=PML_OpenPageFile(gvar);\r
 \r
-       if (!noems)\r
-               PML_StartupEMS();\r
-       if (!noxms)\r
-               PML_StartupXMS();\r
+       if (!noems && MML_CheckForEMS())\r
+               PML_StartupEMS(gvar);\r
+       if (!noxms && MML_CheckForXMS())\r
+               PML_StartupXMS(gvar);\r
+       if(!nomain)\r
+               PML_StartupMainMem(gvar);\r
 \r
-       if (nomain && !EMSPresent)
+       if (!gvar->pm.mm.MainPresent && !gvar->pm.emm.EMSPresent && !gvar->pm.xmm.XMSPresent)\r
        {\r
-               printf("PM_Startup: No main or EMS\n");
-               return;
+               Quit("PM_Startup: No main or EMS\n");\r
+               //return;\r
        }\r
-       else\r
-               PML_StartupMainMem();\r
 \r
-       PM_Reset();\r
+       PM_Reset(gvar);\r
 \r
-       PMStarted = true;\r
+       gvar->pm.PMStarted = true;\r
 }\r
 \r
 //\r
 //     PM_Shutdown() - Shut down the Page Mgr\r
 //\r
 void\r
-PM_Shutdown(void)\r
+PM_Shutdown(global_game_variables_t *gvar)\r
 {\r
-       PML_ShutdownXMS();\r
-       PML_ShutdownEMS();\r
+       if(MML_CheckForXMS()) PML_ShutdownXMS(gvar);\r
+       if(MML_CheckForEMS()) PML_ShutdownEMS(gvar);\r
 \r
-       if (!PMStarted)\r
+       if (!gvar->pm.PMStarted)\r
                return;\r
 \r
-       PML_ClosePageFile();\r
+       //PML_ClosePageFile(gvar);\r
 \r
-       PML_ShutdownMainMem();\r
+       PML_ShutdownMainMem(gvar);\r
 }\r
index 54f1600b4133d117dec8fd6506d67d90c2f4ebf6..4c015e987fd351f39029c6f4f805b821f2d6db43 100755 (executable)
@@ -1,3 +1,28 @@
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#ifndef __16_PM__\r
+#define __16_PM__\r
+\r
 //\r
 //     ID_PM.H\r
 //     Header file for Id Engine's Page Manager\r
@@ -6,8 +31,14 @@
 #include "src/lib/16_head.h"\r
 #include "src/lib/16_hc.h"\r
 #include "src/lib/16_mm.h"\r
+#include "src/lib/16_ca.h"\r
+#include <dos.h>\r
+\r
+#ifdef __DEBUG__\r
+extern boolean dbg_debugpm;\r
+#endif\r
 \r
-//     NOTE! PMPageSize must be an even divisor of EMSPageSize, and >= 1024\r
+/*//   NOTE! PMPageSize must be an even divisor of EMSPageSize, and >= 1024\r
 #define        EMSPageSize             16384\r
 #define        EMSPageSizeSeg  (EMSPageSize >> 4)\r
 #define        EMSPageSizeKB   (EMSPageSize >> 10)\r
@@ -38,7 +69,7 @@ typedef       enum
 \r
 typedef        struct\r
                {\r
-                       longword        offset;         // Offset of chunk into file\r
+                       dword   offset;         // Offset of chunk into file\r
                        word            length;         // Length of the chunk\r
 \r
                        int                     xmsPage;        // If in XMS, (xmsPage * PMPageSize) gives offset into XMS handle\r
@@ -47,13 +78,13 @@ typedef     struct
                        int                     emsPage;        // If in EMS, logical page/offset into page\r
                        int                     mainPage;       // If in Main, index into handle array\r
 \r
-                       longword        lastHit;        // Last frame number of hit\r
+                       dword   lastHit;        // Last frame number of hit\r
                } PageListStruct;\r
 \r
 typedef        struct\r
                {\r
                        int                     baseEMSPage;    // Base EMS page for this phys frame\r
-                       longword        lastHit;                // Last frame number of hit\r
+                       dword   lastHit;                // Last frame number of hit\r
                } EMSListStruct;\r
 \r
 extern boolean                 XMSPresent,EMSPresent;\r
@@ -61,27 +92,29 @@ extern      word                    XMSPagesAvail,EMSPagesAvail;
 \r
 extern word                    ChunksInFile,\r
                                                PMSpriteStart,PMSoundStart;\r
-extern PageListStruct  far *PMPages;\r
+extern PageListStruct  far *PMPages;*///moved to src/lib/typdefst.h\r
 \r
 #define        PM_GetSoundPage(v)      PM_GetPage(PMSoundStart + (v))\r
 #define        PM_GetSpritePage(v)     PM_GetPage(PMSpriteStart + (v))\r
 \r
-#define        PM_LockMainMem()        PM_SetMainMemPurge(0)\r
-#define        PM_UnlockMainMem()      PM_SetMainMemPurge(3)\r
+#define        PM_LockMainMem(gvar)    PM_SetMainMemPurge(0, gvar)\r
+#define        PM_UnlockMainMem(gvar)  PM_SetMainMemPurge(3, gvar)\r
 \r
 \r
 extern char    PageFileName[13];\r
 \r
 \r
-extern void    PM_Startup(void),\r
-                               PM_Shutdown(void),\r
-                               PM_Reset(void),\r
-                               PM_Preload(boolean (*update)(word current,word total)),\r
-                               PM_NextFrame(void),\r
-                               PM_SetPageLock(int pagenum,PMLockType lock),\r
+extern void    PM_Startup(global_game_variables_t *gvar),\r
+                               PM_Shutdown(global_game_variables_t *gvar),\r
+                               PM_Reset(global_game_variables_t *gvar),\r
+                               PM_Preload(boolean (*update)(word current,word total), global_game_variables_t *gvar),\r
+                               PM_NextFrame(global_game_variables_t *gvar),\r
+                               PM_SetPageLock(int pagenum,PMLockType lock, global_game_variables_t *gvar),\r
                                PM_SetMainPurge(int level),\r
-                               PM_CheckMainMem(void);\r
-extern memptr  PM_GetPageAddress(int pagenum),\r
-                               PM_GetPage(int pagenum);                // Use this one to cache page\r
+                               PM_CheckMainMem(global_game_variables_t *gvar);\r
+extern memptr  PM_GetPageAddress(int pagenum, global_game_variables_t *gvar),\r
+                               PM_GetPage(int pagenum, global_game_variables_t *gvar);         // Use this one to cache page\r
 \r
-void PM_SetMainMemPurge(int level);\r
+void PM_SetMainMemPurge(int level, global_game_variables_t *gvar);\r
+void PML_StartupMainMem(global_game_variables_t *gvar);\r
+#endif\r
index c5158dc5d318e6836808b20e366351a2cf9e9cd2..c59590cefe640158f0ac0ee4455574506b971d8d 100755 (executable)
-#include "src/lib/16_sprit.h"
-
-char* get_curr_anim_name(struct sprite *spri)
-{
-       // Retrive animation name list
-       struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr;
-       uint32_t huge *anim_names_offsets =     (uint32_t huge *)
-                                               ((byte huge *)vrs +
-                                                vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_NAME_LIST]);
-
-       return (char *)(vrs + anim_names_offsets[spri->curr_anim]);
-}
-
-void init_anim(struct sprite *spri, int anim_index)
-{
-       struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr;
-       uint32_t huge *anim_lists_offsets =     (uint32_t huge *)
-                                               ((byte huge *)vrs +
-                                                vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_LIST]);
-       struct vrs_animation_list_entry_t huge *anim_list =     (struct vrs_animation_list_entry_t huge *)
-                                                               ((byte huge *)vrs +
-                                                                anim_lists_offsets[anim_index]);
-
-       // Upon new animation, start from the first sprite in it
-       spri->curr_anim = anim_index;
-       spri->curr_anim_spri = 0;
-       spri->curr_spri_id = anim_list[0].sprite_id;
-       spri->delay = anim_list[0].delay;
-
-       spri->curr_anim_list = anim_list;
-}
-
-
-int set_anim_by_id(struct sprite *spri, int anim_id)
-{
-       int new_anim_index = 0;
-       int iter_id;
-       struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr;
-       // Retruve animation ids list
-        uint16_t huge *anim_ids =      (uint16_t huge *)
-                                       ((byte huge *)vrs +
-                                        vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_ID_LIST]);
-
-       // Loop through animation id untill match or end of list
-       while(iter_id = anim_ids[new_anim_index])
-       {
-               // Return on successful match
-               if (iter_id == anim_id)
-               {
-                       init_anim(spri, new_anim_index);
-                       return 0;
-               }
-               new_anim_index++;
-       }
-       return -1;
-}
-
-void print_anim_ids(struct sprite *spri)
-{
-       int new_anim_index = 0;
-       int iter_id;
-       struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr;
-       // Retruve animation ids list
-        uint16_t huge *anim_ids =      (uint16_t huge *)
-                                       ((byte huge *)vrs +
-                                        vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_ID_LIST]);
-
-       if(!anim_ids[new_anim_index])
-               exit(3);
-       // Loop through animation id untill match or end of list
-       while(iter_id = anim_ids[new_anim_index])
-       {
-               // Return on successful match
-               new_anim_index++;
-       }
-}
-
-
-void animate_spri(struct sprite *spri)
-{
-       int i;
-       // Events go here
-
-       // Draw sprite
-       i = get_vrl_by_id(spri->spritesheet, spri->curr_spri_id, spri->sprite_vrl_cont);
-       if(i < 0)
-       {
-               printf("Error retriving required sprite");
-               exit(-1);
-       }
-       draw_vrl1_vgax_modex(   spri->x, spri->y,
-                               spri->sprite_vrl_cont->vrl_header, spri->sprite_vrl_cont->line_offsets,
-                               spri->sprite_vrl_cont->buffer + sizeof(struct vrl1_vgax_header),
-                               spri->sprite_vrl_cont->data_size);
-
-       // Depending on delay, update indices
-       switch(spri->delay){
-               // Delay = 0 means that sprite should loop. Nothing to change here
-               case 0:
-                       break;
-
-               // Delay = 1 means that on next time unit sprite should be changed
-               case 1:
-                       spri->curr_anim_spri++;
-
-                       // If we hit the end of an animation sequence, restart it
-                       if(!(spri->curr_spri_id = spri->curr_anim_list[spri->curr_anim_spri].sprite_id)){
-                               spri->curr_anim_spri = 0;
-                               spri->curr_spri_id = spri->curr_anim_list[spri->curr_anim_spri].sprite_id;
-                       }
-                       spri->delay = spri->curr_anim_list[spri->curr_anim_spri].delay;
-
-               // Delay > 1 means that we should not change sprite yet. Decrease delay
-               default:
-                       spri->delay--;
-                       break;
-       }
-}
+#include "src/lib/16_sprit.h"\r
+\r
+char* get_curr_anim_name(struct sprite *spri)\r
+{\r
+       // Retrive animation name list\r
+       struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr;\r
+       uint32_t huge *anim_names_offsets =     (uint32_t huge *)\r
+                                               ((byte huge *)vrs +\r
+                                                vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_NAME_LIST]);\r
+\r
+       return (char *)(vrs + anim_names_offsets[spri->curr_anim]);\r
+}\r
+\r
+void init_anim(struct sprite *spri, int anim_index)\r
+{\r
+       struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr;\r
+       uint32_t huge *anim_lists_offsets =     (uint32_t huge *)\r
+                                               ((byte huge *)vrs +\r
+                                                vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_LIST]);\r
+       struct vrs_animation_list_entry_t huge *anim_list =     (struct vrs_animation_list_entry_t huge *)\r
+                                                               ((byte huge *)vrs +\r
+                                                                anim_lists_offsets[anim_index]);\r
+\r
+       // Upon new animation, start from the first sprite in it\r
+       spri->curr_anim = anim_index;\r
+       spri->curr_anim_spri = 0;\r
+       spri->curr_spri_id = anim_list[0].sprite_id;\r
+       spri->delay = anim_list[0].delay;\r
+\r
+       spri->curr_anim_list = anim_list;\r
+}\r
+\r
+\r
+int set_anim_by_id(struct sprite *spri, int anim_id)\r
+{\r
+       int new_anim_index = 0;\r
+       int iter_id;\r
+       struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr;\r
+       // Retruve animation ids list\r
+        uint16_t huge *anim_ids =      (uint16_t huge *)\r
+                                       ((byte huge *)vrs +\r
+                                        vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_ID_LIST]);\r
+\r
+       // Loop through animation id untill match or end of list\r
+       while(iter_id = anim_ids[new_anim_index])\r
+       {\r
+               // Return on successful match\r
+               if (iter_id == anim_id)\r
+               {\r
+                       init_anim(spri, new_anim_index);\r
+                       return 0;\r
+               }\r
+               new_anim_index++;\r
+       }\r
+       return -1;\r
+}\r
+\r
+void print_anim_ids(struct sprite *spri)\r
+{\r
+       int new_anim_index = 0;\r
+       int iter_id;\r
+       struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr;\r
+       // Retruve animation ids list\r
+        uint16_t huge *anim_ids =      (uint16_t huge *)\r
+                                       ((byte huge *)vrs +\r
+                                        vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_ID_LIST]);\r
+\r
+       if(!anim_ids[new_anim_index])\r
+               exit(3);\r
+       // Loop through animation id untill match or end of list\r
+       while(iter_id = anim_ids[new_anim_index])\r
+       {\r
+               // Return on successful match\r
+               new_anim_index++;\r
+       }\r
+}\r
+\r
+\r
+void animate_spri(struct sprite *spri)\r
+{\r
+       int i;\r
+       // Events go here\r
+\r
+       // Draw sprite\r
+       i = get_vrl_by_id(spri->spritesheet, spri->curr_spri_id, spri->sprite_vrl_cont);\r
+       if(i < 0)\r
+       {\r
+               printf("Error retriving required sprite");\r
+               exit(-1);\r
+       }\r
+       draw_vrl1_vgax_modex(   spri->x, spri->y,\r
+                               spri->sprite_vrl_cont->vrl_header, spri->sprite_vrl_cont->line_offsets,\r
+                               spri->sprite_vrl_cont->buffer + sizeof(struct vrl1_vgax_header),\r
+                               spri->sprite_vrl_cont->data_size);\r
+\r
+       // Depending on delay, update indices\r
+       switch(spri->delay){\r
+               // Delay = 0 means that sprite should loop. Nothing to change here\r
+               case 0:\r
+                       break;\r
+\r
+               // Delay = 1 means that on next time unit sprite should be changed\r
+               case 1:\r
+                       spri->curr_anim_spri++;\r
+\r
+                       // If we hit the end of an animation sequence, restart it\r
+                       if(!(spri->curr_spri_id = spri->curr_anim_list[spri->curr_anim_spri].sprite_id)){\r
+                               spri->curr_anim_spri = 0;\r
+                               spri->curr_spri_id = spri->curr_anim_list[spri->curr_anim_spri].sprite_id;\r
+                       }\r
+                       spri->delay = spri->curr_anim_list[spri->curr_anim_spri].delay;\r
+\r
+               // Delay > 1 means that we should not change sprite yet. Decrease delay\r
+               default:\r
+                       spri->delay--;\r
+                       break;\r
+       }\r
+}\r
index a93838ace685a54dd0c4aab65acbb50b0a79424b..555e8d1c67c5689743bf1d5e9db4cae8996f17f2 100755 (executable)
@@ -1,74 +1,74 @@
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-#ifndef __16_SPRI__
-#define __16_SPRI__
-
-#include "src/lib/16_vrs.h"
-#include "src/lib/typdefst.h"
-
-struct sprite
-{
-       // VRS container from which we will extract animation and image data
-       struct vrs_container *spritesheet;
-       // Container for a vrl sprite
-       struct vrl_container *sprite_vrl_cont;
-       // Current sprite id
-       int curr_spri_id;
-       // Index of a current sprite in an animation sequence
-       int curr_anim_spri;
-       // Current animation sequence
-       struct vrs_animation_list_entry_t *curr_anim_list;
-       // Index of current animation in relevant VRS offsets table
-       int curr_anim;
-       // Delay in time units untill we should change sprite
-       int delay;
-       // Position of sprite on screen
-       int x, y;
-};
-
-/* Retrive current animation name of sprite
-* In:
-* + struct sprite *spri - sprite to retrive current animation sequence name from
-* Out:
-* + char* - animation sequence name
-*/
-char* get_curr_anim_name(struct sprite *spri);
-
-/* Change sprite's current animation to the one given by id
- * In:
- * struct sprite *spri - sprite to manipulate on
- * int id - id of a new animation sequence of th sprite
- * Out:
- * int - 0 on success, -1 on error
- */
-int set_anim_by_id(struct sprite *spri, int id);
-
-/* Animate sprite, triggering any events and changing indices if necessary
- * NB: if you want to change animation sequence after a specific sprite is shown, you should call animate_spri first
- * In:
- * + struct sprite *spri - sprite to animate
- */
-void animate_spri(struct sprite *spri);
-
-void print_anim_ids(struct sprite *spri);
-
-#endif
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+#ifndef __16_SPRI__\r
+#define __16_SPRI__\r
+\r
+#include "src/lib/16_vrs.h"\r
+#include "src/lib/typdefst.h"\r
+\r
+struct sprite\r
+{\r
+       // VRS container from which we will extract animation and image data\r
+       struct vrs_container *spritesheet;\r
+       // Container for a vrl sprite\r
+       struct vrl_container *sprite_vrl_cont;\r
+       // Current sprite id\r
+       int curr_spri_id;\r
+       // Index of a current sprite in an animation sequence\r
+       int curr_anim_spri;\r
+       // Current animation sequence\r
+       struct vrs_animation_list_entry_t *curr_anim_list;\r
+       // Index of current animation in relevant VRS offsets table\r
+       int curr_anim;\r
+       // Delay in time units untill we should change sprite\r
+       int delay;\r
+       // Position of sprite on screen\r
+       int x, y;\r
+};\r
+\r
+/* Retrive current animation name of sprite\r
+* In:\r
+* + struct sprite *spri - sprite to retrive current animation sequence name from\r
+* Out:\r
+* + char* - animation sequence name\r
+*/\r
+char* get_curr_anim_name(struct sprite *spri);\r
+\r
+/* Change sprite's current animation to the one given by id\r
+ * In:\r
+ * struct sprite *spri - sprite to manipulate on\r
+ * int id - id of a new animation sequence of th sprite\r
+ * Out:\r
+ * int - 0 on success, -1 on error\r
+ */\r
+int set_anim_by_id(struct sprite *spri, int id);\r
+\r
+/* Animate sprite, triggering any events and changing indices if necessary\r
+ * NB: if you want to change animation sequence after a specific sprite is shown, you should call animate_spri first\r
+ * In:\r
+ * + struct sprite *spri - sprite to animate\r
+ */\r
+void animate_spri(struct sprite *spri);\r
+\r
+void print_anim_ids(struct sprite *spri);\r
+\r
+#endif\r
diff --git a/src/lib/16_tail.c b/src/lib/16_tail.c
new file mode 100755 (executable)
index 0000000..f63dddc
--- /dev/null
@@ -0,0 +1,207 @@
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+/*\r
+ * 16 library\r
+ */\r
+\r
+#include "src/lib/16_tail.h"\r
+\r
+/*\r
+==========================\r
+=\r
+= Startup16\r
+=\r
+= Load a few things right away\r
+=\r
+==========================\r
+*/\r
+\r
+void Startup16(global_game_variables_t *gvar)\r
+{\r
+#ifdef __WATCOMC__\r
+       // DOSLIB: check our environment\r
+       probe_dos();\r
+\r
+       // DOSLIB: what CPU are we using?\r
+       // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS.\r
+       //      So this code by itself shouldn't care too much what CPU it's running on. Except that other\r
+       //      parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for\r
+       //      the CPU to carry out tasks. --J.C.\r
+       cpu_probe();\r
+\r
+       // DOSLIB: check for VGA\r
+       if (!probe_vga()) {\r
+               printf("VGA probe failed\n");\r
+               return;\r
+       }\r
+       // hardware must be VGA or higher!\r
+       if (!(vga_state.vga_flags & VGA_IS_VGA)) {\r
+               printf("This program requires VGA or higher graphics hardware\n");\r
+               return;\r
+       }\r
+\r
+       if (_DEBUG_INIT() == 0) {\r
+#ifdef DEBUGSERIAL\r
+               printf("WARNING: Failed to initialize DEBUG output\n");\r
+#endif\r
+       }\r
+       _DEBUG("Serial debug output started\n"); // NTS: All serial output must end messages with newline, or DOSBox-X will not emit text to log\r
+       _DEBUGF("Serial debug output printf test %u %u %u\n",1U,2U,3U);\r
+#endif\r
+       gvar->mm.mmstarted=0;\r
+       gvar->pm.PMStarted=0;\r
+       MM_Startup(gvar);\r
+       IN_Startup(gvar);\r
+       PM_Startup(gvar);\r
+       PM_UnlockMainMem(gvar);\r
+       CA_Startup(gvar);\r
+#ifdef __WATCOMC__\r
+       start_timer(gvar);\r
+       \r
+#endif\r
+\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==========================\r
+=\r
+= Shutdown16\r
+=\r
+= Shuts down all ID_?? managers\r
+=\r
+==========================\r
+*/\r
+\r
+void Shutdown16(global_game_variables_t *gvar)\r
+{\r
+       PM_Shutdown(gvar);\r
+       IN_Shutdown(gvar);\r
+       CA_Shutdown(gvar);\r
+       MM_Shutdown(gvar);\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= DebugMemory\r
+=\r
+==================\r
+*/\r
+\r
+void DebugMemory_(global_game_variables_t *gvar, boolean q)\r
+{\r
+       /*VW_FixRefreshBuffer ();\r
+       US_CenterWindow (16,7);\r
+\r
+       US_CPrint ("Memory Usage");\r
+       US_CPrint ("------------");\r
+       US_Print ("Total     :");\r
+       US_PrintUnsigned (mminfo.mainmem/1024);\r
+       US_Print ("k\nFree      :");\r
+       US_PrintUnsigned (MM_UnusedMemory()/1024);\r
+       US_Print ("k\nWith purge:");\r
+       US_PrintUnsigned (MM_TotalFree()/1024);\r
+       US_Print ("k\n");\r
+       VW_UpdateScreen();*/\r
+       if(q){\r
+       printf("========================================\n");\r
+       printf("                DebugMemory_\n");\r
+       printf("========================================\n");}\r
+       if(q) { printf("Memory Usage\n");\r
+       printf("------------\n"); }else printf("        %c%c", 0xD3, 0xC4);\r
+       printf("Total:  "); if(q) printf("      "); printf("%uk", gvar->mmi.mainmem/1024);\r
+       if(q) printf("\n"); else printf("       ");\r
+       printf("Free:   "); if(q) printf("      "); printf("%uk", MM_UnusedMemory(gvar)/1024);\r
+       if(q) printf("\n"); else printf("       ");\r
+       printf("With purge:"); if(q) printf("   "); printf("%uk\n", MM_TotalFree(gvar)/1024);\r
+       if(q) printf("------------\n");\r
+#ifdef __WATCOMC__\r
+       IN_Ack ();\r
+#endif\r
+       if(q) MM_ShowMemory (gvar);\r
+}\r
+#ifdef __WATCOMC__\r
+/*\r
+==========================\r
+=\r
+= Quit\r
+=\r
+==========================\r
+*/\r
+\r
+void Quit (char *error)\r
+{\r
+       unsigned        finscreen;\r
+       memptr  screen;\r
+       union REGS in, out;\r
+\r
+       //ClearMemory ();\r
+       if (!*error)\r
+       {\r
+        //WriteConfig ();\r
+       }\r
+       else\r
+       {\r
+        //CA_CacheGrChunk (ERRORSCREEN);\r
+        //screen = grsegs[ERRORSCREEN];\r
+       }\r
+\r
+       //ShutdownId ();\r
+       IN_Shutdown();\r
+       //modexLeave();\r
+       in.h.ah = 0x00;\r
+       in.h.al = 0x3;\r
+       int86(0x10, &in, &out);\r
+\r
+       if (error && *error)\r
+       {\r
+         //movedata ((unsigned)screen,7,0xb800,0,7*160);\r
+         //gotoxy (10,4);\r
+         fprintf(stderr, "%s\n", error);\r
+         //gotoxy (1,8);\r
+         exit(1);\r
+       }\r
+       else\r
+       if (!error || !(*error))\r
+       {\r
+               //clrscr();\r
+               //#ifndef JAPAN\r
+               movedata ((unsigned)screen,7,0xb800,0,4000);\r
+               //gotoxy(1,24);\r
+               //#endif\r
+//asm  mov     bh,0\r
+//asm  mov     dh,23   // row\r
+//asm  mov     dl,0    // collumn\r
+//asm  mov ah,2\r
+//asm  int     0x10\r
+       }\r
+\r
+       exit(0);\r
+}\r
+#endif\r
+\r
+//===========================================================================\r
diff --git a/src/lib/16_tail.h b/src/lib/16_tail.h
new file mode 100755 (executable)
index 0000000..d9d37b1
--- /dev/null
@@ -0,0 +1,41 @@
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#ifndef        __16_TAIL__\r
+#define        __16_TAIL__\r
+\r
+#include "src/lib/16_head.h"\r
+#include "src/lib/16_pm.h"\r
+#include "src/lib/16_mm.h"\r
+#include "src/lib/16_ca.h"\r
+#include "src/lib/16_in.h"\r
+\r
+extern boolean dbg_debugpm;\r
+\r
+void DebugMemory_(global_game_variables_t *gvar, boolean q);\r
+void Shutdown16(global_game_variables_t *gvar);\r
+void Startup16(global_game_variables_t *gvar);\r
+#ifdef __WATCOMC__\r
+void Quit (char *error);\r
+#endif\r
+\r
+#endif\r
index 5dc525e15d39c237e6783525de42f6538eed733b..595489d69fe760f647ba7de213369a4aa2625e5b 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-#include "src/lib/16_vrs.h"
-#include "src/lib/typdefst.h"
-
-// Read .vrs file into far memory
-int read_vrs(global_game_variables_t *gvar, char *filename, struct vrs_container *vrs_cont){
-       int fd;
-       dword size;
-#ifdef __WATCOMC__
-       __segment seg;
-       void __based(seg)* bigbuffer;
-#endif
-#ifdef __BORLANDC__
-       memptr bigbuffer;
-#endif
-       byte huge *buffer;
-       vrl1_vgax_offset_t **vrl_line_offsets;
-       uint32_t huge *vrl_headers_offsets;
-       uint16_t huge *vrl_id_iter;
-       uint32_t vrl_size;
-       int num_of_vrl, i;
-       struct vrl1_vgax_header huge *curr_vrl;
-       int success;
-
-       // Open filename, get size of file,
-       // populate the vrs_container if all tests pass
-       fd = open(filename, O_RDONLY|O_BINARY);
-       // Insert sanity cheks later
-       size = lseek(fd, 0, SEEK_END);
-       buffer = malloc(size);
-       lseek(fd, 0, SEEK_SET);
-       read(fd, buffer, size);
-       close(fd);
-       if(!success)
-       {
-               fprintf(stderr, "Unablee to load file");
-               exit(3);
-       }
-       vrs_cont->data_size = size - sizeof(struct vrs_header);
-       vrs_cont->buffer = buffer;
-
-       // Calculate vrl offsets
-       
-       // Count sprites
-       vrl_id_iter = (uint16_t huge *)(buffer + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]);
-       while(vrl_id_iter[num_of_vrl]){
-               num_of_vrl++;
-       }
-       // Allocate memory for vrl line offsets table
-       vrl_line_offsets = malloc(sizeof(vrl1_vgax_offset_t *)*num_of_vrl);
-
-       vrl_headers_offsets = (uint32_t huge *)(buffer + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]);
-       // Calculate line offsets for each vrl
-       for(i = 0; i < num_of_vrl; i++){
-               curr_vrl = (struct vrl1_vgax_header huge *)(buffer + vrl_headers_offsets[i]);
-
-               // Calc. vrl size as (next_offset - curr_offset)
-               if (i != num_of_vrl - 1){
-                       vrl_size = vrl_headers_offsets[i+1] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header);
-               }
-               // If it's the last vrl, size is (next_vrs_struct_offset - curr_offset)
-               else{
-                       vrl_size = vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header);
-               }
-               vrl_line_offsets[i] = vrl1_vgax_genlineoffsets(curr_vrl, (byte *)curr_vrl + sizeof(struct vrl1_vgax_header), vrl_size);
-       }
-       vrs_cont->vrl_line_offsets = vrl_line_offsets;
-       return 0;
-}
-
-// Seek and return a specified .vrl blob from .vrs blob in far memory
-int get_vrl_by_id(struct vrs_container /*huge*/ *vrs_cont, uint16_t id, struct vrl_container *vrl_cont){
-       uint16_t huge *ids;
-       uint32_t huge *vrl_offs_list;
-       int counter = 0;
-
-       // If id is invalid, return -1
-       if(id == 0){
-               // Probably add an error message?
-               return -1;
-       }
-
-       // Get id list from .vrs blob (base + offset)
-       ids = (uint16_t huge*)(vrs_cont->buffer + 
-               vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]);
-
-       // Loop through the id list until we found the right one or hit the end of the list
-       // Counter is keeping track of the offset(in ids/vrl blobs)
-       while(ids[counter] != id && ids[counter]){
-               counter++;
-       }
-       // Return -2 if we couldn't find the requested id
-       if(!ids[counter]){
-               // Error message?
-               return -2;
-       }
-
-       // Get vrl offsets list from .vrs blob (base + offset)
-       vrl_offs_list = (uint32_t huge *)(vrs_cont->buffer +
-                                       vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]);
-
-       // Get vrl_header from .vrs (base + offset from vrl_list)
-       // Counter is number of vrls to skip (ids and vrls are aligned according to the .vrs specification)
-       vrl_cont->vrl_header = (struct vrl1_vgax_header huge *)(vrs_cont->buffer + vrl_offs_list[counter]);
-
-       // Get .vrl size by integer arithmetics (next vrl offset - current vrl offset)
-       if(ids[counter+1]){
-               vrl_cont->data_size = vrl_offs_list[counter+1] - vrl_offs_list[counter] - sizeof(struct vrl1_vgax_header);
-       }
-       // If we are retriving the last vrl, size is ids_list offset - current vrl offset, as next vrl offs is 0
-       else{
-               vrl_cont->data_size = vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_offs_list[counter] - sizeof(struct vrl1_vgax_header);
-       }
-
-       // Retrive line offsets form .vrs
-       vrl_cont->line_offsets = vrs_cont->vrl_line_offsets[counter];
-
-       return 0;
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+#include "src/lib/16_vrs.h"\r
+#include "src/lib/typdefst.h"\r
+\r
+// Read .vrs file into far memory\r
+int read_vrs(global_game_variables_t *gvar, char *filename, struct vrs_container *vrs_cont){\r
+       int fd;\r
+       dword size;\r
+#ifdef __WATCOMC__\r
+       __segment seg;\r
+       void __based(seg)* bigbuffer;\r
+#endif\r
+#ifdef __BORLANDC__\r
+       memptr bigbuffer;\r
+#endif\r
+       byte huge *buffer;\r
+       vrl1_vgax_offset_t **vrl_line_offsets;\r
+       uint32_t huge *vrl_headers_offsets;\r
+       uint16_t huge *vrl_id_iter;\r
+       uint32_t vrl_size;\r
+       int num_of_vrl, i;\r
+       struct vrl1_vgax_header huge *curr_vrl;\r
+       int success;\r
+\r
+       // Open filename, get size of file,\r
+       // populate the vrs_container if all tests pass\r
+       fd = open(filename, O_RDONLY|O_BINARY);\r
+       // Insert sanity cheks later\r
+       size = lseek(fd, 0, SEEK_END);\r
+       buffer = malloc(size);\r
+       lseek(fd, 0, SEEK_SET);\r
+       read(fd, buffer, size);\r
+       close(fd);\r
+       if(!success)\r
+       {\r
+               fprintf(stderr, "Unablee to load file");\r
+               exit(3);\r
+       }\r
+       vrs_cont->data_size = size - sizeof(struct vrs_header);\r
+       vrs_cont->buffer = buffer;\r
+\r
+       // Calculate vrl offsets\r
+       \r
+       // Count sprites\r
+       vrl_id_iter = (uint16_t huge *)(buffer + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]);\r
+       while(vrl_id_iter[num_of_vrl]){\r
+               num_of_vrl++;\r
+       }\r
+       // Allocate memory for vrl line offsets table\r
+       vrl_line_offsets = malloc(sizeof(vrl1_vgax_offset_t *)*num_of_vrl);\r
+\r
+       vrl_headers_offsets = (uint32_t huge *)(buffer + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]);\r
+       // Calculate line offsets for each vrl\r
+       for(i = 0; i < num_of_vrl; i++){\r
+               curr_vrl = (struct vrl1_vgax_header huge *)(buffer + vrl_headers_offsets[i]);\r
+\r
+               // Calc. vrl size as (next_offset - curr_offset)\r
+               if (i != num_of_vrl - 1){\r
+                       vrl_size = vrl_headers_offsets[i+1] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header);\r
+               }\r
+               // If it's the last vrl, size is (next_vrs_struct_offset - curr_offset)\r
+               else{\r
+                       vrl_size = vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header);\r
+               }\r
+               vrl_line_offsets[i] = vrl1_vgax_genlineoffsets(curr_vrl, (byte *)curr_vrl + sizeof(struct vrl1_vgax_header), vrl_size);\r
+       }\r
+       vrs_cont->vrl_line_offsets = vrl_line_offsets;\r
+       return 0;\r
+}\r
+\r
+// Seek and return a specified .vrl blob from .vrs blob in far memory\r
+int get_vrl_by_id(struct vrs_container /*huge*/ *vrs_cont, uint16_t id, struct vrl_container *vrl_cont){\r
+       uint16_t huge *ids;\r
+       uint32_t huge *vrl_offs_list;\r
+       int counter = 0;\r
+\r
+       // If id is invalid, return -1\r
+       if(id == 0){\r
+               // Probably add an error message?\r
+               return -1;\r
+       }\r
+\r
+       // Get id list from .vrs blob (base + offset)\r
+       ids = (uint16_t huge*)(vrs_cont->buffer + \r
+               vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]);\r
+\r
+       // Loop through the id list until we found the right one or hit the end of the list\r
+       // Counter is keeping track of the offset(in ids/vrl blobs)\r
+       while(ids[counter] != id && ids[counter]){\r
+               counter++;\r
+       }\r
+       // Return -2 if we couldn't find the requested id\r
+       if(!ids[counter]){\r
+               // Error message?\r
+               return -2;\r
+       }\r
+\r
+       // Get vrl offsets list from .vrs blob (base + offset)\r
+       vrl_offs_list = (uint32_t huge *)(vrs_cont->buffer +\r
+                                       vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]);\r
+\r
+       // Get vrl_header from .vrs (base + offset from vrl_list)\r
+       // Counter is number of vrls to skip (ids and vrls are aligned according to the .vrs specification)\r
+       vrl_cont->vrl_header = (struct vrl1_vgax_header huge *)(vrs_cont->buffer + vrl_offs_list[counter]);\r
+\r
+       // Get .vrl size by integer arithmetics (next vrl offset - current vrl offset)\r
+       if(ids[counter+1]){\r
+               vrl_cont->data_size = vrl_offs_list[counter+1] - vrl_offs_list[counter] - sizeof(struct vrl1_vgax_header);\r
+       }\r
+       // If we are retriving the last vrl, size is ids_list offset - current vrl offset, as next vrl offs is 0\r
+       else{\r
+               vrl_cont->data_size = vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_offs_list[counter] - sizeof(struct vrl1_vgax_header);\r
+       }\r
+\r
+       // Retrive line offsets form .vrs\r
+       vrl_cont->line_offsets = vrs_cont->vrl_line_offsets[counter];\r
+\r
+       return 0;\r
+}\r
index 381b7108dbea75e39c4be851a361960a46d64456..cdeb81a0cf74a1cdfa97abff15bacb9c76857419 100755 (executable)
@@ -1,78 +1,78 @@
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-#ifndef __16_VRS__
-#define __16_VRS__
-
-#include "src/lib/modex16.h"
-#include "src/lib/typdefst.h"
-//#include <hw/cpu/cpu.h>
-//#include <hw/dos/dos.h>
-#include <hw/vga/vrl.h>
-#include "src/lib/16_ca.h"
-
-struct vrs_container{
-       // Size of a .vrs lob in memory
-       // minus header
-       dword data_size;
-       union{
-               byte huge *buffer;
-               struct vrs_header huge *vrs_hdr;
-       };
-       // Array of corresponding vrl line offsets
-       vrl1_vgax_offset_t **vrl_line_offsets;
-};
-
-struct vrl_container{
-       // Size of a .vrl blob in memory
-       // minus header
-       dword data_size;
-       union{
-               byte huge *buffer;
-               struct vrl1_vgax_header huge *vrl_header;
-       };
-       // Pointer to a corresponding vrl line offsets struct
-       vrl1_vgax_offset_t *line_offsets;
-};
-
-/* Read .vrs file into memory
-* In:
-* + char *filename - name of the file to load
-* + struct vrs_container *vrs_cont - pointer to the vrs_container
-* to load the file into
-* Out:
-* + int - 0 on succes, 1 on failure
-*/
-int read_vrs(global_game_variables_t *gvar, char *filename, struct vrs_container *vrs_cont);
-
-/* Seek and return a specified .vrl blob from .vrs blob in memory
-* In:
-* + struct vrs_container *vrs_cont - pointer to the vrs_container
-* with a loaded .vrs file
-* + uint16_t id - id of the vrl to retrive
-* + struct vrl_container * vrl_cont - pointer to vrl_container to load to
-* Out:
-* int - operation status
-* to the requested .vrl blob
-*/
-int get_vrl_by_id(struct vrs_container *vrs_cont, uint16_t id, struct vrl_container * vrl_cont);
-
-#endif
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+#ifndef __16_VRS__\r
+#define __16_VRS__\r
+\r
+#include "src/lib/modex16.h"\r
+#include "src/lib/typdefst.h"\r
+//#include <hw/cpu/cpu.h>\r
+//#include <hw/dos/dos.h>\r
+#include <hw/vga/vrl.h>\r
+#include "src/lib/16_ca.h"\r
+\r
+struct vrs_container{\r
+       // Size of a .vrs lob in memory\r
+       // minus header\r
+       dword data_size;\r
+       union{\r
+               byte huge *buffer;\r
+               struct vrs_header huge *vrs_hdr;\r
+       };\r
+       // Array of corresponding vrl line offsets\r
+       vrl1_vgax_offset_t **vrl_line_offsets;\r
+};\r
+\r
+struct vrl_container{\r
+       // Size of a .vrl blob in memory\r
+       // minus header\r
+       dword data_size;\r
+       union{\r
+               byte huge *buffer;\r
+               struct vrl1_vgax_header huge *vrl_header;\r
+       };\r
+       // Pointer to a corresponding vrl line offsets struct\r
+       vrl1_vgax_offset_t *line_offsets;\r
+};\r
+\r
+/* Read .vrs file into memory\r
+* In:\r
+* + char *filename - name of the file to load\r
+* + struct vrs_container *vrs_cont - pointer to the vrs_container\r
+* to load the file into\r
+* Out:\r
+* + int - 0 on succes, 1 on failure\r
+*/\r
+int read_vrs(global_game_variables_t *gvar, char *filename, struct vrs_container *vrs_cont);\r
+\r
+/* Seek and return a specified .vrl blob from .vrs blob in memory\r
+* In:\r
+* + struct vrs_container *vrs_cont - pointer to the vrs_container\r
+* with a loaded .vrs file\r
+* + uint16_t id - id of the vrl to retrive\r
+* + struct vrl_container * vrl_cont - pointer to vrl_container to load to\r
+* Out:\r
+* int - operation status\r
+* to the requested .vrl blob\r
+*/\r
+int get_vrl_by_id(struct vrs_container *vrs_cont, uint16_t id, struct vrl_container * vrl_cont);\r
+\r
+#endif\r
index 2dc6f5aa088258665dcebda37c6610007a39d171..e152ce18fc08b460687c050a7cf815793e5d8975 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/*
-       scroll16 library~
-*/
-#include "src/lib/scroll16.h"
-#include "src/lib/16_sprite.h"
-
-void walk(map_view_t *pip, player_t *player, word pn)
-{
-       #define INC_PER_FRAME if(player[pn].q&1) player[pn].persist_aniframe++; if(player[pn].persist_aniframe>4) player[pn].persist_aniframe = 1;
-       //printf("player[%d].d=%d\n", pn, player[pn].d);
-       switch(player[pn].d)
-       {
-               //no direction
-               case 2:
-                       //0000pip[0].video->startclk = (*clockw);
-               break;
-               //right movement
-               case 3:
-                       //printf("pip[0].page->tilesw=%d        ", pip[0].page->tilesw); printf("pip[0].page->tw=%d\n", pip[0].page->tw);
-                       if(pip[0].tx >= 0 && pip[0].tx+pip[0].page->tw < pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx &&
-                       !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY))      //collision detection!
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       animatePlayer(pip, player, pn, 1);
-                                       ScrollRight(pip, player, 3, pn);
-                                       ScrollRight(pip, player, 2, pn);
-                                       mapScrollRight(pip, player, !(pip[0].video->p), pn);
-                                       mapScrollRight(pip, player, (pip[0].video->p), pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; }
-                       }
-                       else if(player[pn].tx < pip[0].map->width && !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY))
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       player[pn].x+=(player[pn].speed);
-                                       animatePlayer(pip, player, pn, 0);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; }
-                       }
-                       else
-                       {
-                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32);
-#ifdef SPRITE
-                               //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 16, 32, PLAYERBMPDATA);
-                               animate_spri(player[pn].spri);
-#else
-                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 14);
-#endif
-                               if(!pageflipflop) modexShowPage(pip[1].page);
-                               player[pn].d = 2;
-                       }
-                       player[pn].triggerx = player[pn].tx+1;
-                       player[pn].triggery = player[pn].ty;
-               break;
-
-               //left movement
-               case 1:
-                       if(pip[0].tx > 0 && pip[0].tx+pip[0].page->tw <= pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx &&
-                       !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY))    //collision detection!
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       animatePlayer(pip, player, pn, 1);
-                                       ScrollLeft(pip, player, 3, pn);
-                                       ScrollLeft(pip, player, 2, pn);
-                                       mapScrollLeft(pip, player, !(pip[0].video->p), pn);
-                                       mapScrollLeft(pip, player, (pip[0].video->p), pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; }
-                       }
-                       else if(player[pn].tx > 1 && !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY))
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       player[pn].x-=(player[pn].speed);
-                                       animatePlayer(pip, player, pn, 0);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; }
-                       }
-                       else
-                       {
-                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32);
-#ifdef SPRITE
-                               //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 96, 16, 32, PLAYERBMPDATA);
-                               animate_spri(player[pn].spri);
-#else
-                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 10);
-#endif
-                               if(!pageflipflop) modexShowPage(pip[1].page);
-                               player[pn].d = 2;
-                       }
-                       player[pn].triggerx = player[pn].tx-1;
-                       player[pn].triggery = player[pn].ty;
-               break;
-
-               //down movement
-               case 4:
-                       if(pip[0].ty >= 0 && pip[0].ty+pip[0].page->th < pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny &&
-                       !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY))      //collision detection!
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       animatePlayer(pip, player, pn, 1);
-                                       ScrollDown(pip, player, 3, pn);
-                                       ScrollDown(pip, player, 2, pn);
-                                       mapScrollDown(pip, player, !(pip[0].video->p), pn);
-                                       mapScrollDown(pip, player, (pip[0].video->p), pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; }
-                       }
-                       else if(player[pn].ty < pip[0].map->height && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY))
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       player[pn].y+=(player[pn].speed);
-                                       animatePlayer(pip, player, pn, 0);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; }
-                       }
-                       else
-                       {
-                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32);
-#ifdef SPRITE
-                               //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 64, 16, 32, PLAYERBMPDATA);
-                               animate_spri(player[pn].spri);
-#else
-                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 9);
-#endif
-                               if(!pageflipflop) modexShowPage(pip[1].page);
-                               player[pn].d = 2;
-                       }
-                       player[pn].triggerx = player[pn].tx;
-                       player[pn].triggery = player[pn].ty+1;
-               break;
-
-               //up movement
-               case 0:
-                       if(pip[0].ty > 0 && pip[0].ty+pip[0].page->th <= pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny &&
-                       !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY))    //collision detection!
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       animatePlayer(pip, player, pn, 1);
-                                       ScrollUp(pip, player, 3, pn);
-                                       ScrollUp(pip, player, 2, pn);
-                                       mapScrollUp(pip, player, !(pip[0].video->p), pn);
-                                       mapScrollUp(pip, player, (pip[0].video->p), pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; }
-                       }
-                       else if(player[pn].ty > 1 && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX &&  player[pn].ty-1 == TRIGGY))
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       player[pn].y-=(player[pn].speed);
-                                       animatePlayer(pip, player, 0, pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; }
-                       }
-                       else
-                       {
-                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32);
-#ifdef SPRITE
-                               //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 0, 16, 32, PLAYERBMPDATA);
-                               animate_spri(player[pn].spri);
-#else
-                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 12);
-#endif
-                               if(!pageflipflop) modexShowPage(pip[1].page);
-                               player[pn].d = 2;
-                       }
-                       player[pn].triggerx = player[pn].tx;
-                       player[pn].triggery = player[pn].ty-1;
-               break;
-       }
-}
-
-//panning page
-void panpagemanual(map_view_t *pip, player_t *player, word pn)
-{
-       switch(player[pn].d)
-       {
-               //right movement
-               case 3:
-                       if(pip[pip[0].pan->pn].tx >= 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw < pip[pip[0].pan->pn].page->tilesw)
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       pip[pip[0].pan->pn].page->dx+=4;
-                                       modexShowPage(pip[pip[0].pan->pn].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx++; }
-                       }
-               break;
-
-               //left movement
-               case 1:
-                       if(pip[pip[0].pan->pn].tx > 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw <= pip[pip[0].pan->pn].page->tilesw)
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       pip[pip[0].pan->pn].page->dx-=4;
-                                       modexShowPage(pip[pip[0].pan->pn].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx--; }
-                       }
-               break;
-
-               //down movement
-               case 4:
-                       if(pip[pip[0].pan->pn].ty >= 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th < pip[pip[0].pan->pn].page->tilesh)
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       pip[pip[0].pan->pn].page->dy+=4;
-                                       modexShowPage(pip[pip[0].pan->pn].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty++; }
-                       }
-               break;
-
-               //up movement
-               case 0:
-                       if(pip[pip[0].pan->pn].ty > 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th <= pip[pip[0].pan->pn].page->tilesh)
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       pip[pip[0].pan->pn].page->dy-=4;
-                                       modexShowPage(pip[pip[0].pan->pn].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty--; }
-                       }
-                       break;
-       }
-       //if (player[pn].d!=2) printf("player[%u].d=%u player[%u].q=%u\n", pn, player[pn].d, pn, player[pn].q);
-}
-
-/*map_t
-allocMap(int w, int h) {
-       map_t result;
-
-       result.width =w;
-       result.height=h;
-       result.data = malloc(sizeof(byte) * w * h);
-       //result.data = (byte *)alloc_emem(((int)sizeof(byte) * w * h)/1024);
-       if(isEMS() || checkEMS())
-       {
-               XMOVE mm;
-               //emmhandle = mallocEMS(coretotalEMS());//alloc_emem((int)sizeof(map))
-               mm.length=sizeof(result);
-               mm.sourceH=0;
-               mm.sourceOff=ptr2long(&result);
-               mm.destH=emmhandle;
-               mm.destOff=0;
-               ist = move_emem(&mm);
-               if(!ist){ dealloc_emem(emmhandle); exit(5); }
-               printf("%d\n", coretotalEMS());
-       }
-
-       return result;
-}*/
-
-/*void
-initMap(map_t *map) {
-       // just a place holder to fill out an alternating pattern
-       int x, y, xx, yy;
-       int i, q;
-//     int tile = 1;
-       //if(!isEMS() || !checkEMS())
-//             map->tiles = malloc(sizeof(tiles_t));
-       //else
-       //      map->tiles = (tiles_t *)alloc_emem(sizeof(tiles_t));
-
-        //create the tile set
-       //if(!isEMS() || !checkEMS())
-//             map->tiles->data = malloc(sizeof(bitmap_t));
-       //else
-       //      map->tiles->data = (bitmap_t *)alloc_emem(sizeof(bitmap_t));
-//     map->tiles->data->width = (TILEWH);
-//     map->tiles->data->height= TILEWH;
-       //if(!isEMS() || !checkEMS())
-//             map->tiles->data->data = malloc((TILEWH*2)*TILEWH);
-       //else
-       //      map->tiles->data->data = (byte *)alloc_emem((TILEWH*2)*TILEWH);
-//     map->tiles->tileHeight = TILEWH;
-//     map->tiles->tileWidth =TILEWH;
-//     map->tiles->rows = 1;
-//     map->tiles->cols = 1;//2;
-
-       q=0;
-       //for(y=0; y<map->height; y++) {
-       //for(x=0; x<map->width; x++) {
-       i=0;
-       for(yy=0; yy<TILEWH; yy++) {
-       for(xx=0; xx<(TILEWH); xx++) {
-               //if(x<TILEWH){
-                 map->tiles->data->data[i+1] = map->data[q];//28;//0x24;
-//               printf("[%d]", map->tiles->data->data[i]);
-               //}else{
-                 //map->tiles->data->data[i] = map->data[q];//0;//0x34;
-                 //printf("]%d[==[%d]", i, map->tiles->data->data[i]);
-               //}
-               i++;
-       }
-//     printf("\n");
-       }
-//     printf("[%d]", map->data[q]);
-       q++;
-//     }
-       //printf("\n\n");
-//     }
-
-       i=0;
-       for(y=0; y<map->height; y++) {
-               for(x=0; x<map->width; x++) {
-//                     map->data[i]=255;
-                       printf("[%d]", map->data[i]);
-                       //tile = tile ? 0 : 1;
-                       i++;
-               }
-               //tile = tile ? 0 : 1;
-       }
-}*/
-
-void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid)
-{
-       word x, y;  /* coordinate for drawing */
-
-       /* increment the pixel position and update the page */
-       mv[id].page->dx += player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dx >= mv[id].dxThresh )
-       {
-       /* go forward one tile */
-       mv[id].tx++;
-       /* Snap the origin forward */
-       mv[id].page->data += 4;
-
-       mv[id].page->dx = mv[id].map->tiles->tileWidth;
-       }
-
-       /* draw the next column */
-       x= mv[0].page->sw + mv[id].map->tiles->tileWidth;
-       if(player[plid].q%4)
-               if(id==0)
-                       mapDrawCol(&mv[0], mv[0].tx + mv[0].page->tw, mv[0].ty-1, x, player, mv->page->dx);
-               else
-                       if(!pageflipflop && !pageploop)
-                               modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2));
-       mv[0].video->r=1;
-}
-
-
-void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid)
-{
-       word x, y;  /* coordinate for drawing */
-
-       /* decrement the pixel position and update the page */
-       mv[id].page->dx -= player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dx == 0)
-       {
-       /* go backward one tile */
-       mv[id].tx--;
-       /* Snap the origin backward */
-       mv[id].page->data -= 4;
-
-       mv[id].page->dx = mv[id].map->tiles->tileWidth;
-       }
-
-       /* draw the next column */
-       x= 0;
-       if(player[plid].q%4)
-               if(id==0)
-                       mapDrawCol(&mv[0], mv[0].tx - 1, mv[0].ty-1, x, player, mv->page->dx);
-               else
-                       if(!pageflipflop && !pageploop)
-                               modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2));
-       mv[0].video->r=1;
-}
-
-
-void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid)
-{
-       word x, y;  /* coordinate for drawing */
-
-       /* decrement the pixel position and update the page */
-       mv[id].page->dy -= player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dy == 0 )
-       {
-       /* go down one tile */
-       mv[id].ty--;
-       /* Snap the origin downward */
-       mv[id].page->data -= mv[id].page->pi;
-
-       mv[id].page->dy = mv[id].map->tiles->tileHeight;
-       }
-
-       /* draw the next row */
-       y= 0;
-       if(player[plid].q%3)
-               if(id==0)
-                       mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty-1, y, player, mv->page->dy);
-               else
-                       if(!pageflipflop && !pageploop)
-                               modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight);
-       mv[0].video->r=1;
-}
-
-void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid)
-{
-       word x, y;  /* coordinate for drawing */
-
-       /* increment the pixel position and update the page */
-       mv[id].page->dy += player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dy >= mv[id].dyThresh )
-       {
-       /* go down one tile */
-       mv[id].ty++;
-       /* Snap the origin downward */
-       mv[id].page->data += mv[id].page->pi;
-
-       mv[id].page->dy = mv[id].map->tiles->tileHeight;
-       }
-
-       /* draw the next row */
-       y= mv[0].page->sh + mv[id].map->tiles->tileHeight;
-       if(player[plid].q%3)
-               if(id==0)
-                       mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty+mv[0].page->th, y, player, mv->page->dy);
-               else
-                       if(!pageflipflop && !pageploop)
-                               modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight);
-       mv[0].video->r=1;
-}
-
-
-//TODO finish this wwww
-void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid)
-{
-       /* increment the pixel position and update the page */
-       mv[id].page->dx += player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dx >= mv[0].dxThresh )
-       {
-//             vga_setup_wm1_block_copy();
-//             _fmemmove(mv[id].page->data+4, mv[id].page->data, mv[id].page->pagesize);
-//             vga_restore_rm0wm0();
-               /* Snap the origin forward */
-               mv[id].page->data += 4;
-               mv[id].page->dx = mv[0].map->tiles->tileWidth;
-       }
-}
-
-void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid)
-{
-       /* decrement the pixel position and update the page */
-       mv[id].page->dx -= player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dx == 0)
-       {
-//             vga_setup_wm1_block_copy();
-//             _fmemmove(mv[id].page->data-4, mv[id].page->data, mv[id].page->pagesize);
-//             vga_restore_rm0wm0();
-               /* Snap the origin backward */
-               mv[id].page->data -= 4;
-               mv[id].page->dx = mv[0].map->tiles->tileWidth;
-       }
-}
-
-void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid)
-{
-       /* decrement the pixel position and update the page */
-       mv[id].page->dy -= player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dy == 0)
-       {
-//             vga_setup_wm1_block_copy();
-//             _fmemmove(mv[id].page->data-mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize);
-//             vga_restore_rm0wm0();
-               /* Snap the origin backward */
-               mv[id].page->data -= mv[id].page->pi;
-               mv[id].page->dy = mv[0].map->tiles->tileWidth;
-       }
-}
-
-void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid)
-{
-       /* increment the pixel position and update the page */
-       mv[id].page->dy += player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dy >= mv[0].dxThresh )
-       {
-//             vga_setup_wm1_block_copy();
-//             _fmemmove(mv[id].page->data+mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize);
-//             vga_restore_rm0wm0();
-               /* Snap the origin forward */
-               mv[id].page->data += mv[id].page->pi;
-               mv[id].page->dy = mv[0].map->tiles->tileWidth;
-       }
-}
-
-sword chkmap(map_t *map, word q)
-{
-//     bitmap_t bp;
-       static byte x[(MAPW*MAPH)+1] =
-{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 };
-/*1,   2,      3,      4,      0,      3,      3,      3,      3,      3,      3,      3,      3,      4,      1,      1,      1,      1,      1,      1,      \
-5,     6,      7,      8,      0,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-9,     10,     11,     12,     4,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-13,    14,     15,     16,     0,      1,      1,      1,      5,      8,      1,      11,     11,     1,      1,      1,      1,      1,      1,      1,      \
-0,     0,      4,      0,      0,      0,      0,      0,      8,      8,      1,      11,     11,     3,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      0,      0,      0,      0,      8,      8,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      3,      3,      3,      1,      2,      3,      4 };*/
-       //check for failed to load map
-       if((map->width == map->height == 0) && (q>0))
-       {
-               //initiate a null map!
-               map->width=MAPW;///2;
-               map->height=MAPH;///2;
-//             map->data = malloc(((map->width*map->height)+1)*sizeof(byte));
-               map->data = &x;
-               map->tiles = malloc(sizeof(tiles_t));
-               //fix this to be far~
-//             bp = bitmapLoadPcx("data/ed.pcx");
-//             map->tiles->data = &bp;
-               map->tiles->debug_data = map->data;
-               map->tiles->tileHeight = 16;
-               map->tiles->tileWidth = 16;
-               map->tiles->rows = 1;
-               map->tiles->cols = 1;
-               map->tiles->debug_text = true;
-       }
-       else map->tiles->debug_text = false;
-       return 0;
-}
-
-//TODO: player position here
-void mapGoTo(map_view_t *mv, int tx, int ty)
-{
-       int px, py;
-       unsigned int i;
-
-       /* set up the coordinates */
-       mv[0].tx = mv[1].tx = tx;
-       mv[0].ty = mv[1].ty = ty;
-       mv[0].page->dx = mv[1].page->dx = mv[2].page->dx = mv[3].page->dx = mv->map->tiles->tileWidth;
-       mv[0].page->dy = mv[1].page->dy = mv[2].page->dy = mv[3].page->dy = mv->map->tiles->tileHeight;
-
-       /* set up the thresholds */
-       mv[0].dxThresh = mv[1].dxThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileWidth * 2;
-       mv[0].dyThresh = mv[1].dyThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileHeight * 2;
-
-       /* draw the tiles */
-       modexClearRegion(mv[0].page, 0, 0, mv[0].page->width, mv[0].page->height, 0);
-       py=0;
-       i=mv[0].ty * mv[0].map->width + mv[0].tx;
-       for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) {
-               mapDrawWRow(&mv[0], tx-1, ty, py);
-       i+=mv->map->width - tx;
-       }
-       if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height);
-//     {
-//             unsigned int k,j,o;
-//             /* fill screen with a distinctive pattern */
-//             for (k=0;k < vga_state.vga_width;k++) {
-//                     o = k >> 2;
-//                     vga_write_sequencer(0x02/*map mask*/,1 << (k&3));
-//                             for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride)
-//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!
-//             }
-//     }
-       modexCopyPageRegion(mv[3].page, mv[0].page, 0/**/, 0/**/, 0, 0, 16, 32);
-}
-
-void near
-mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y)
-{
-       word rx;
-       word ry;
-       word textx=0;
-       word texty=0;
-       //if(i==0) i=2;
-       if(i==0)
-       {
-               //wwww
-               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color!
-       }
-       else
-       {
-               rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth);
-               ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight);
-////0000printf("i=%d\n", i);
-               switch(t->debug_text)
-               {
-                       case 0:
-#ifndef TILERENDER
-                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1));
-                               //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i]));
-#else
-                               PBUFBFUN                (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));
-                               /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */
-                               //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));
-                               //modexDrawBmpRegion    (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));
-#endif
-                       break;
-                       case 1:
-                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1);
-                               //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data));
-                               /*for(texty=0; texty<2; texty++)
-                               {
-                                       for(textx=0; textx<2; textx++)
-                                       {*/
-//                                             modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data));
-/*                                     }
-                               }*/
-                       break;
-               }
-       }
-}
-
-void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset)
-{
-       word x;
-       int i;
-       poopoffset%=p[0].speed;
-//printf("y: %d\n", poopoffset);
-       /* the position within the map array */
-       i=ty * mv->map->width + tx;
-       for(x=poopoffset; x<(mv->page->sw+mv->dxThresh)/(poopoffset+1) && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) {
-       if(i>=0) {
-               /* we are in the map, so copy! */
-               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);
-       }
-       i++; /* next! */
-       }
-}
-
-void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset)
-{
-       int y;
-       int i;
-       poopoffset%=p[0].speed;
-//printf("x: %d\n", poopoffset);
-       /* location in the map array */
-       i=ty * mv->map->width + tx;
-
-       /* We'll copy all of the columns in the screen,
-          i + 1 row above and one below */
-       for(y=poopoffset; y<(mv->page->sh+mv->dyThresh)/(poopoffset+1) && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) {
-       if(i>=0) {
-               /* we are in the map, so copy away! */
-               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);
-       }
-       i += mv->map->width;
-       }
-}
-
-void mapDrawWRow(map_view_t *mv, int tx, int ty, word y)
-{
-       word x;
-       int i;
-
-       /* the position within the map array */
-       i=ty * mv->map->width + tx;
-       for(x=0; x<mv->page->sw+mv->dxThresh && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) {
-       if(i>=0) {
-               /* we are in the map, so copy! */
-               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);
-       }
-       i++; /* next! */
-       }
-}
-
-void mapDrawWCol(map_view_t *mv, int tx, int ty, word x)
-{
-       int y;
-       int i;
-
-       /* location in the map array */
-       i=ty * mv->map->width + tx;
-
-       /* We'll copy all of the columns in the screen,
-          i + 1 row above and one below */
-       for(y=0; y<mv->page->sh+mv->dyThresh && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) {
-       if(i>=0) {
-               /* we are in the map, so copy away! */
-               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);
-       }
-       i += mv->map->width;
-       }
-}
-
-/*void qclean()
-{
-       //setkb(0);
-}*/
-
-unsigned char shinku_fps_indicator_page = 2;
-boolean pageflipflop = 1;
-boolean pageploop = 1;
-
-/*     sync    */
-void shinku(global_game_variables_t *gv)
-{
-       word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen
-       word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen
-       word w = 64, h = 8, col = 7, bgcol = 0, type = 1;
-       byte o,o2,i;
-       //modexCopyPageRegion(pip[1].page, pip[2].page, 16, 16, 16, 16, (14*8)+4, 8+4);
-       /* block copy to visible RAM from offscreen */
-//     vga_setup_wm1_block_copy();
-//     modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x+w, 0, w, h);
-//     o =     *(gv->video.page[2].data); // source offscreen
-//     o2 =    *(gv->video.page[shinku_fps_indicator_page].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride)
-//     for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);
-       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */
-//     vga_restore_rm0wm0();
-       if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second))
-       {
-               sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv));
-               //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45);
-               modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee);
-               gv->kurokku.tiku=0;
-               /* block copy to visible RAM from offscreen */
-//             vga_setup_wm1_block_copy();
-//             o =     *(gv->video.page[shinku_fps_indicator_page].data); // source offscreen
-//             o2 =    *(gv->video.page[2].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride)
-//             for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);
-//             modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x, 0, w, h);
-               /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */
-//             vga_restore_rm0wm0();
-       }else //copy dat sheet
-       gv->kurokku.tiku++;
-
-       switch(gv->kurokku.fpscap)
-       {
-               case 0:
-                       //modexprint(&(gv->video.page[shinku_fps_indicator_page]), x, y+8, type, col, bgcol, "sanic!");
-                       gv->kurokku.frames_per_second=1;
-               break;
-               case 1:
-                       //turn this off if XT
-                       //modexWaitBorder();
-                       vga_wait_for_vsync();
-                       gv->kurokku.frames_per_second=60;
-               break;
-       }
-       if(pageflipflop){
-       if(gv->video.r){
-               //vga_setup_wm1_block_copy();
-               //_fmemcpy((gv->video.page[(gv->video.p)]).data, (gv->video.page[(!gv->video.p)]).data, gv->video.page[(!gv->video.p)].pagesize);
-               //vga_restore_rm0wm0();
-               if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height);
-               modexShowPage(&(gv->video.page[gv->video.p]));
-               if(!pageploop) gv->video.p=!gv->video.p;
-               gv->video.r=!gv->video.r;
-               //0000gv->video.tickclk = ((*clockw)-gv->video.startclk)/18.2;
-       }
-       }
-}
-
-void near animatePlayer(map_view_t *pip, player_t *player, word pn, sword scrollswitch)
-{
-       sword x = player[pn].x;
-       sword y = player[pn].y;
-       sword bx = x+16;        //buffer's x
-       sword by = y+16;        //buffer's y
-       word dire=32; //direction
-       sword qq; //scroll offset
-       word ls = player[pn].persist_aniframe;
-
-       switch(scrollswitch)
-       {
-               case 0:
-                       qq = 0;
-               break;
-               default:
-                       qq = ((player[pn].q)*(player[pn].speed));
-               break;
-       }
-       //x-=4;
-       y-=pip[0].map->tiles->tileHeight;
-       switch (player[pn].d)
-       {
-               case 0:
-                       //up
-                       dire*=player[pn].d;
-                       y-=qq;
-                       by-=4;
-               break;
-               case 3:
-                       // right
-                       dire*=(player[pn].d-2);
-                       x+=qq;
-                       bx+=4;
-               break;
-               case 2:
-               break;
-               case 4:
-                       //down
-                       dire*=(player[pn].d-2);
-                       y+=qq;
-                       by+=4;
-               break;
-               case 1:
-                       //left
-                       dire*=(player[pn].d+2);
-                       x-=qq;
-                       bx-=4;
-               break;
-       }
-
-#ifdef SPRITE
-//#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 32, dire, 16, 32,      PLAYERBMPDATA);
-//#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 16, dire, 16, 32,      PLAYERBMPDATA);
-//#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 16, 32,       PLAYERBMPDATA);
-//#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 16, dire, 16, 32,      PLAYERBMPDATA);
-#define FRAME1 animate_spri(player[pn].spri);
-#define FRAME2 animate_spri(player[pn].spri);
-#define FRAME3 animate_spri(player[pn].spri);
-#define FRAME4 animate_spri(player[pn].spri);
-#else
-#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 2+dire);
-#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 1+dire);
-#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, dire);
-#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 1+dire);
-#endif
-       if(!pageflipflop)
-               modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 36);
-       else{
-               //copy old bg to page0
-               //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0,   20, 36);
-               //update buffer
-               //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0,   x, y,   20, 36);
-       }
-//modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height);
-       //modexCopyPageRegion(pip[3].page, pip[!(pip->video->p)].page, x-4, y-4, 0, 128, 28, 36);
-       /*modexCopyPageRegion(pip[pip->video->p].page,
- pip[!(pip->video->p)].page, x-4, y-4, x-4, y-4, 28, 36);*/
-//     else modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 40);
-       switch(ls)
-       {
-               case 1:
-                       FRAME1
-               break;
-               case 2:
-                       FRAME2
-               break;
-               case 3:
-                       FRAME3
-               break;
-               case 4:
-                       FRAME4
-               break;
-       }
-//     if(2>ls && ls>=1) { FRAME1 }else
-//     if(3>ls && ls>=2) { FRAME2 }else
-//     if(4>ls && ls>=3) { FRAME3 }else
-//     if(5>ls && ls>=4) { FRAME4 }
-       //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 16, 32);
-       //printf("x=%d  y=%d    bx=%d           by=%d\n", x, y, bx, by);
-       pip->video->r=1;
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+/*\r
+       scroll16 library~\r
+*/\r
+#include "src/lib/scroll16.h"\r
+#include "src/lib/16_sprite.h"\r
+\r
+void walk(map_view_t *pip, player_t *player, word pn)\r
+{\r
+       #define INC_PER_FRAME if(player[pn].q&1) player[pn].persist_aniframe++; if(player[pn].persist_aniframe>4) player[pn].persist_aniframe = 1;\r
+       //printf("player[%d].d=%d\n", pn, player[pn].d);\r
+       switch(player[pn].d)\r
+       {\r
+               //no direction\r
+               case 2:\r
+                       //0000pip[0].video->startclk = (*clockw);\r
+               break;\r
+               //right movement\r
+               case 3:\r
+                       //printf("pip[0].page->tilesw=%d        ", pip[0].page->tilesw); printf("pip[0].page->tw=%d\n", pip[0].page->tw);\r
+                       if(pip[0].tx >= 0 && pip[0].tx+pip[0].page->tw < pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx &&\r
+                       !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY))      //collision detection!\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       animatePlayer(pip, player, pn, 1);\r
+                                       ScrollRight(pip, player, 3, pn);\r
+                                       ScrollRight(pip, player, 2, pn);\r
+                                       mapScrollRight(pip, player, !(pip[0].video->p), pn);\r
+                                       mapScrollRight(pip, player, (pip[0].video->p), pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; }\r
+                       }\r
+                       else if(player[pn].tx < pip[0].map->width && !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY))\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       player[pn].x+=(player[pn].speed);\r
+                                       animatePlayer(pip, player, pn, 0);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; }\r
+                       }\r
+                       else\r
+                       {\r
+                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32);\r
+#ifdef SPRITE\r
+                               //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 16, 32, PLAYERBMPDATA);\r
+                               animate_spri(player[pn].spri);\r
+#else\r
+                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 14);\r
+#endif\r
+                               if(!pageflipflop) modexShowPage(pip[1].page);\r
+                               player[pn].d = 2;\r
+                       }\r
+                       player[pn].triggerx = player[pn].tx+1;\r
+                       player[pn].triggery = player[pn].ty;\r
+               break;\r
+\r
+               //left movement\r
+               case 1:\r
+                       if(pip[0].tx > 0 && pip[0].tx+pip[0].page->tw <= pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx &&\r
+                       !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY))    //collision detection!\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       animatePlayer(pip, player, pn, 1);\r
+                                       ScrollLeft(pip, player, 3, pn);\r
+                                       ScrollLeft(pip, player, 2, pn);\r
+                                       mapScrollLeft(pip, player, !(pip[0].video->p), pn);\r
+                                       mapScrollLeft(pip, player, (pip[0].video->p), pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; }\r
+                       }\r
+                       else if(player[pn].tx > 1 && !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY))\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       player[pn].x-=(player[pn].speed);\r
+                                       animatePlayer(pip, player, pn, 0);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; }\r
+                       }\r
+                       else\r
+                       {\r
+                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32);\r
+#ifdef SPRITE\r
+                               //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 96, 16, 32, PLAYERBMPDATA);\r
+                               animate_spri(player[pn].spri);\r
+#else\r
+                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 10);\r
+#endif\r
+                               if(!pageflipflop) modexShowPage(pip[1].page);\r
+                               player[pn].d = 2;\r
+                       }\r
+                       player[pn].triggerx = player[pn].tx-1;\r
+                       player[pn].triggery = player[pn].ty;\r
+               break;\r
+\r
+               //down movement\r
+               case 4:\r
+                       if(pip[0].ty >= 0 && pip[0].ty+pip[0].page->th < pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny &&\r
+                       !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY))      //collision detection!\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       animatePlayer(pip, player, pn, 1);\r
+                                       ScrollDown(pip, player, 3, pn);\r
+                                       ScrollDown(pip, player, 2, pn);\r
+                                       mapScrollDown(pip, player, !(pip[0].video->p), pn);\r
+                                       mapScrollDown(pip, player, (pip[0].video->p), pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; }\r
+                       }\r
+                       else if(player[pn].ty < pip[0].map->height && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY))\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       player[pn].y+=(player[pn].speed);\r
+                                       animatePlayer(pip, player, pn, 0);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; }\r
+                       }\r
+                       else\r
+                       {\r
+                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32);\r
+#ifdef SPRITE\r
+                               //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 64, 16, 32, PLAYERBMPDATA);\r
+                               animate_spri(player[pn].spri);\r
+#else\r
+                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 9);\r
+#endif\r
+                               if(!pageflipflop) modexShowPage(pip[1].page);\r
+                               player[pn].d = 2;\r
+                       }\r
+                       player[pn].triggerx = player[pn].tx;\r
+                       player[pn].triggery = player[pn].ty+1;\r
+               break;\r
+\r
+               //up movement\r
+               case 0:\r
+                       if(pip[0].ty > 0 && pip[0].ty+pip[0].page->th <= pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny &&\r
+                       !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY))    //collision detection!\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       animatePlayer(pip, player, pn, 1);\r
+                                       ScrollUp(pip, player, 3, pn);\r
+                                       ScrollUp(pip, player, 2, pn);\r
+                                       mapScrollUp(pip, player, !(pip[0].video->p), pn);\r
+                                       mapScrollUp(pip, player, (pip[0].video->p), pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; }\r
+                       }\r
+                       else if(player[pn].ty > 1 && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX &&  player[pn].ty-1 == TRIGGY))\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       player[pn].y-=(player[pn].speed);\r
+                                       animatePlayer(pip, player, 0, pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; }\r
+                       }\r
+                       else\r
+                       {\r
+                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32);\r
+#ifdef SPRITE\r
+                               //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 0, 16, 32, PLAYERBMPDATA);\r
+                               animate_spri(player[pn].spri);\r
+#else\r
+                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 12);\r
+#endif\r
+                               if(!pageflipflop) modexShowPage(pip[1].page);\r
+                               player[pn].d = 2;\r
+                       }\r
+                       player[pn].triggerx = player[pn].tx;\r
+                       player[pn].triggery = player[pn].ty-1;\r
+               break;\r
+       }\r
+}\r
+\r
+//panning page\r
+void panpagemanual(map_view_t *pip, player_t *player, word pn)\r
+{\r
+       switch(player[pn].d)\r
+       {\r
+               //right movement\r
+               case 3:\r
+                       if(pip[pip[0].pan->pn].tx >= 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw < pip[pip[0].pan->pn].page->tilesw)\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       pip[pip[0].pan->pn].page->dx+=4;\r
+                                       modexShowPage(pip[pip[0].pan->pn].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx++; }\r
+                       }\r
+               break;\r
+\r
+               //left movement\r
+               case 1:\r
+                       if(pip[pip[0].pan->pn].tx > 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw <= pip[pip[0].pan->pn].page->tilesw)\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       pip[pip[0].pan->pn].page->dx-=4;\r
+                                       modexShowPage(pip[pip[0].pan->pn].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx--; }\r
+                       }\r
+               break;\r
+\r
+               //down movement\r
+               case 4:\r
+                       if(pip[pip[0].pan->pn].ty >= 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th < pip[pip[0].pan->pn].page->tilesh)\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       pip[pip[0].pan->pn].page->dy+=4;\r
+                                       modexShowPage(pip[pip[0].pan->pn].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty++; }\r
+                       }\r
+               break;\r
+\r
+               //up movement\r
+               case 0:\r
+                       if(pip[pip[0].pan->pn].ty > 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th <= pip[pip[0].pan->pn].page->tilesh)\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       pip[pip[0].pan->pn].page->dy-=4;\r
+                                       modexShowPage(pip[pip[0].pan->pn].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty--; }\r
+                       }\r
+                       break;\r
+       }\r
+       //if (player[pn].d!=2) printf("player[%u].d=%u player[%u].q=%u\n", pn, player[pn].d, pn, player[pn].q);\r
+}\r
+\r
+/*map_t\r
+allocMap(int w, int h) {\r
+       map_t result;\r
+\r
+       result.width =w;\r
+       result.height=h;\r
+       result.data = malloc(sizeof(byte) * w * h);\r
+       //result.data = (byte *)alloc_emem(((int)sizeof(byte) * w * h)/1024);\r
+       if(isEMS() || checkEMS())\r
+       {\r
+               XMOVE mm;\r
+               //emmhandle = mallocEMS(coretotalEMS());//alloc_emem((int)sizeof(map))\r
+               mm.length=sizeof(result);\r
+               mm.sourceH=0;\r
+               mm.sourceOff=ptr2long(&result);\r
+               mm.destH=emmhandle;\r
+               mm.destOff=0;\r
+               ist = move_emem(&mm);\r
+               if(!ist){ dealloc_emem(emmhandle); exit(5); }\r
+               printf("%d\n", coretotalEMS());\r
+       }\r
+\r
+       return result;\r
+}*/\r
+\r
+/*void\r
+initMap(map_t *map) {\r
+       // just a place holder to fill out an alternating pattern\r
+       int x, y, xx, yy;\r
+       int i, q;\r
+//     int tile = 1;\r
+       //if(!isEMS() || !checkEMS())\r
+//             map->tiles = malloc(sizeof(tiles_t));\r
+       //else\r
+       //      map->tiles = (tiles_t *)alloc_emem(sizeof(tiles_t));\r
+\r
+        //create the tile set\r
+       //if(!isEMS() || !checkEMS())\r
+//             map->tiles->data = malloc(sizeof(bitmap_t));\r
+       //else\r
+       //      map->tiles->data = (bitmap_t *)alloc_emem(sizeof(bitmap_t));\r
+//     map->tiles->data->width = (TILEWH);\r
+//     map->tiles->data->height= TILEWH;\r
+       //if(!isEMS() || !checkEMS())\r
+//             map->tiles->data->data = malloc((TILEWH*2)*TILEWH);\r
+       //else\r
+       //      map->tiles->data->data = (byte *)alloc_emem((TILEWH*2)*TILEWH);\r
+//     map->tiles->tileHeight = TILEWH;\r
+//     map->tiles->tileWidth =TILEWH;\r
+//     map->tiles->rows = 1;\r
+//     map->tiles->cols = 1;//2;\r
+\r
+       q=0;\r
+       //for(y=0; y<map->height; y++) {\r
+       //for(x=0; x<map->width; x++) {\r
+       i=0;\r
+       for(yy=0; yy<TILEWH; yy++) {\r
+       for(xx=0; xx<(TILEWH); xx++) {\r
+               //if(x<TILEWH){\r
+                 map->tiles->data->data[i+1] = map->data[q];//28;//0x24;\r
+//               printf("[%d]", map->tiles->data->data[i]);\r
+               //}else{\r
+                 //map->tiles->data->data[i] = map->data[q];//0;//0x34;\r
+                 //printf("]%d[==[%d]", i, map->tiles->data->data[i]);\r
+               //}\r
+               i++;\r
+       }\r
+//     printf("\n");\r
+       }\r
+//     printf("[%d]", map->data[q]);\r
+       q++;\r
+//     }\r
+       //printf("\n\n");\r
+//     }\r
+\r
+       i=0;\r
+       for(y=0; y<map->height; y++) {\r
+               for(x=0; x<map->width; x++) {\r
+//                     map->data[i]=255;\r
+                       printf("[%d]", map->data[i]);\r
+                       //tile = tile ? 0 : 1;\r
+                       i++;\r
+               }\r
+               //tile = tile ? 0 : 1;\r
+       }\r
+}*/\r
+\r
+void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* increment the pixel position and update the page */\r
+       mv[id].page->dx += player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dx >= mv[id].dxThresh )\r
+       {\r
+       /* go forward one tile */\r
+       mv[id].tx++;\r
+       /* Snap the origin forward */\r
+       mv[id].page->data += 4;\r
+\r
+       mv[id].page->dx = mv[id].map->tiles->tileWidth;\r
+       }\r
+\r
+       /* draw the next column */\r
+       x= mv[0].page->sw + mv[id].map->tiles->tileWidth;\r
+       if(player[plid].q%4)\r
+               if(id==0)\r
+                       mapDrawCol(&mv[0], mv[0].tx + mv[0].page->tw, mv[0].ty-1, x, player, mv->page->dx);\r
+               else\r
+                       if(!pageflipflop && !pageploop)\r
+                               modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2));\r
+       mv[0].video->r=1;\r
+}\r
+\r
+\r
+void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* decrement the pixel position and update the page */\r
+       mv[id].page->dx -= player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dx == 0)\r
+       {\r
+       /* go backward one tile */\r
+       mv[id].tx--;\r
+       /* Snap the origin backward */\r
+       mv[id].page->data -= 4;\r
+\r
+       mv[id].page->dx = mv[id].map->tiles->tileWidth;\r
+       }\r
+\r
+       /* draw the next column */\r
+       x= 0;\r
+       if(player[plid].q%4)\r
+               if(id==0)\r
+                       mapDrawCol(&mv[0], mv[0].tx - 1, mv[0].ty-1, x, player, mv->page->dx);\r
+               else\r
+                       if(!pageflipflop && !pageploop)\r
+                               modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2));\r
+       mv[0].video->r=1;\r
+}\r
+\r
+\r
+void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* decrement the pixel position and update the page */\r
+       mv[id].page->dy -= player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dy == 0 )\r
+       {\r
+       /* go down one tile */\r
+       mv[id].ty--;\r
+       /* Snap the origin downward */\r
+       mv[id].page->data -= mv[id].page->pi;\r
+\r
+       mv[id].page->dy = mv[id].map->tiles->tileHeight;\r
+       }\r
+\r
+       /* draw the next row */\r
+       y= 0;\r
+       if(player[plid].q%3)\r
+               if(id==0)\r
+                       mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty-1, y, player, mv->page->dy);\r
+               else\r
+                       if(!pageflipflop && !pageploop)\r
+                               modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight);\r
+       mv[0].video->r=1;\r
+}\r
+\r
+void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* increment the pixel position and update the page */\r
+       mv[id].page->dy += player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dy >= mv[id].dyThresh )\r
+       {\r
+       /* go down one tile */\r
+       mv[id].ty++;\r
+       /* Snap the origin downward */\r
+       mv[id].page->data += mv[id].page->pi;\r
+\r
+       mv[id].page->dy = mv[id].map->tiles->tileHeight;\r
+       }\r
+\r
+       /* draw the next row */\r
+       y= mv[0].page->sh + mv[id].map->tiles->tileHeight;\r
+       if(player[plid].q%3)\r
+               if(id==0)\r
+                       mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty+mv[0].page->th, y, player, mv->page->dy);\r
+               else\r
+                       if(!pageflipflop && !pageploop)\r
+                               modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight);\r
+       mv[0].video->r=1;\r
+}\r
+\r
+\r
+//TODO finish this wwww\r
+void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       /* increment the pixel position and update the page */\r
+       mv[id].page->dx += player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dx >= mv[0].dxThresh )\r
+       {\r
+//             vga_setup_wm1_block_copy();\r
+//             _fmemmove(mv[id].page->data+4, mv[id].page->data, mv[id].page->pagesize);\r
+//             vga_restore_rm0wm0();\r
+               /* Snap the origin forward */\r
+               mv[id].page->data += 4;\r
+               mv[id].page->dx = mv[0].map->tiles->tileWidth;\r
+       }\r
+}\r
+\r
+void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       /* decrement the pixel position and update the page */\r
+       mv[id].page->dx -= player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dx == 0)\r
+       {\r
+//             vga_setup_wm1_block_copy();\r
+//             _fmemmove(mv[id].page->data-4, mv[id].page->data, mv[id].page->pagesize);\r
+//             vga_restore_rm0wm0();\r
+               /* Snap the origin backward */\r
+               mv[id].page->data -= 4;\r
+               mv[id].page->dx = mv[0].map->tiles->tileWidth;\r
+       }\r
+}\r
+\r
+void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       /* decrement the pixel position and update the page */\r
+       mv[id].page->dy -= player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dy == 0)\r
+       {\r
+//             vga_setup_wm1_block_copy();\r
+//             _fmemmove(mv[id].page->data-mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize);\r
+//             vga_restore_rm0wm0();\r
+               /* Snap the origin backward */\r
+               mv[id].page->data -= mv[id].page->pi;\r
+               mv[id].page->dy = mv[0].map->tiles->tileWidth;\r
+       }\r
+}\r
+\r
+void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       /* increment the pixel position and update the page */\r
+       mv[id].page->dy += player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dy >= mv[0].dxThresh )\r
+       {\r
+//             vga_setup_wm1_block_copy();\r
+//             _fmemmove(mv[id].page->data+mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize);\r
+//             vga_restore_rm0wm0();\r
+               /* Snap the origin forward */\r
+               mv[id].page->data += mv[id].page->pi;\r
+               mv[id].page->dy = mv[0].map->tiles->tileWidth;\r
+       }\r
+}\r
+\r
+sword chkmap(map_t *map, word q)\r
+{\r
+//     bitmap_t bp;\r
+       static byte x[(MAPW*MAPH)+1] =\r
+{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 };\r
+/*1,   2,      3,      4,      0,      3,      3,      3,      3,      3,      3,      3,      3,      4,      1,      1,      1,      1,      1,      1,      \\r
+5,     6,      7,      8,      0,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+9,     10,     11,     12,     4,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+13,    14,     15,     16,     0,      1,      1,      1,      5,      8,      1,      11,     11,     1,      1,      1,      1,      1,      1,      1,      \\r
+0,     0,      4,      0,      0,      0,      0,      0,      8,      8,      1,      11,     11,     3,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      0,      0,      0,      0,      8,      8,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      3,      3,      3,      1,      2,      3,      4 };*/\r
+       //check for failed to load map\r
+       if((map->width == map->height == 0) && (q>0))\r
+       {\r
+               //initiate a null map!\r
+               map->width=MAPW;///2;\r
+               map->height=MAPH;///2;\r
+//             map->data = malloc(((map->width*map->height)+1)*sizeof(byte));\r
+               map->data = &x;\r
+               map->tiles = malloc(sizeof(tiles_t));\r
+               //fix this to be far~\r
+//             bp = bitmapLoadPcx("data/ed.pcx");\r
+//             map->tiles->data = &bp;\r
+               map->tiles->debug_data = map->data;\r
+               map->tiles->tileHeight = 16;\r
+               map->tiles->tileWidth = 16;\r
+               map->tiles->rows = 1;\r
+               map->tiles->cols = 1;\r
+               map->tiles->debug_text = true;\r
+       }\r
+       else map->tiles->debug_text = false;\r
+       return 0;\r
+}\r
+\r
+//TODO: player position here\r
+void mapGoTo(map_view_t *mv, int tx, int ty)\r
+{\r
+       int px, py;\r
+       unsigned int i;\r
+\r
+       /* set up the coordinates */\r
+       mv[0].tx = mv[1].tx = tx;\r
+       mv[0].ty = mv[1].ty = ty;\r
+       mv[0].page->dx = mv[1].page->dx = mv[2].page->dx = mv[3].page->dx = mv->map->tiles->tileWidth;\r
+       mv[0].page->dy = mv[1].page->dy = mv[2].page->dy = mv[3].page->dy = mv->map->tiles->tileHeight;\r
+\r
+       /* set up the thresholds */\r
+       mv[0].dxThresh = mv[1].dxThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileWidth * 2;\r
+       mv[0].dyThresh = mv[1].dyThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileHeight * 2;\r
+\r
+       /* draw the tiles */\r
+       modexClearRegion(mv[0].page, 0, 0, mv[0].page->width, mv[0].page->height, 0);\r
+       py=0;\r
+       i=mv[0].ty * mv[0].map->width + mv[0].tx;\r
+       for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) {\r
+               mapDrawWRow(&mv[0], tx-1, ty, py);\r
+       i+=mv->map->width - tx;\r
+       }\r
+       if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height);\r
+//     {\r
+//             unsigned int k,j,o;\r
+//             /* fill screen with a distinctive pattern */\r
+//             for (k=0;k < vga_state.vga_width;k++) {\r
+//                     o = k >> 2;\r
+//                     vga_write_sequencer(0x02/*map mask*/,1 << (k&3));\r
+//                             for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride)\r
+//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!\r
+//             }\r
+//     }\r
+       modexCopyPageRegion(mv[3].page, mv[0].page, 0/**/, 0/**/, 0, 0, 16, 32);\r
+}\r
+\r
+void near\r
+mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y)\r
+{\r
+       word rx;\r
+       word ry;\r
+       word textx=0;\r
+       word texty=0;\r
+       //if(i==0) i=2;\r
+       if(i==0)\r
+       {\r
+               //wwww\r
+               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color!\r
+       }\r
+       else\r
+       {\r
+               rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth);\r
+               ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight);\r
+////0000printf("i=%d\n", i);\r
+               switch(t->debug_text)\r
+               {\r
+                       case 0:\r
+#ifndef TILERENDER\r
+                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1));\r
+                               //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i]));\r
+#else\r
+                               PBUFBFUN                (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));\r
+                               /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */\r
+                               //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));\r
+                               //modexDrawBmpRegion    (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));\r
+#endif\r
+                       break;\r
+                       case 1:\r
+                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1);\r
+                               //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data));\r
+                               /*for(texty=0; texty<2; texty++)\r
+                               {\r
+                                       for(textx=0; textx<2; textx++)\r
+                                       {*/\r
+//                                             modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data));\r
+/*                                     }\r
+                               }*/\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset)\r
+{\r
+       word x;\r
+       int i;\r
+       poopoffset%=p[0].speed;\r
+//printf("y: %d\n", poopoffset);\r
+       /* the position within the map array */\r
+       i=ty * mv->map->width + tx;\r
+       for(x=poopoffset; x<(mv->page->sw+mv->dxThresh)/(poopoffset+1) && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i++; /* next! */\r
+       }\r
+}\r
+\r
+void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset)\r
+{\r
+       int y;\r
+       int i;\r
+       poopoffset%=p[0].speed;\r
+//printf("x: %d\n", poopoffset);\r
+       /* location in the map array */\r
+       i=ty * mv->map->width + tx;\r
+\r
+       /* We'll copy all of the columns in the screen,\r
+          i + 1 row above and one below */\r
+       for(y=poopoffset; y<(mv->page->sh+mv->dyThresh)/(poopoffset+1) && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy away! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i += mv->map->width;\r
+       }\r
+}\r
+\r
+void mapDrawWRow(map_view_t *mv, int tx, int ty, word y)\r
+{\r
+       word x;\r
+       int i;\r
+\r
+       /* the position within the map array */\r
+       i=ty * mv->map->width + tx;\r
+       for(x=0; x<mv->page->sw+mv->dxThresh && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i++; /* next! */\r
+       }\r
+}\r
+\r
+void mapDrawWCol(map_view_t *mv, int tx, int ty, word x)\r
+{\r
+       int y;\r
+       int i;\r
+\r
+       /* location in the map array */\r
+       i=ty * mv->map->width + tx;\r
+\r
+       /* We'll copy all of the columns in the screen,\r
+          i + 1 row above and one below */\r
+       for(y=0; y<mv->page->sh+mv->dyThresh && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy away! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i += mv->map->width;\r
+       }\r
+}\r
+\r
+/*void qclean()\r
+{\r
+       //setkb(0);\r
+}*/\r
+\r
+unsigned char shinku_fps_indicator_page = 2;\r
+boolean pageflipflop = 1;\r
+boolean pageploop = 1;\r
+\r
+/*     sync    */\r
+void shinku(global_game_variables_t *gv)\r
+{\r
+       word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen\r
+       word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen\r
+       word w = 64, h = 8, col = 7, bgcol = 0, type = 1;\r
+       byte o,o2,i;\r
+       //modexCopyPageRegion(pip[1].page, pip[2].page, 16, 16, 16, 16, (14*8)+4, 8+4);\r
+       /* block copy to visible RAM from offscreen */\r
+//     vga_setup_wm1_block_copy();\r
+//     modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x+w, 0, w, h);\r
+//     o =     *(gv->video.page[2].data); // source offscreen\r
+//     o2 =    *(gv->video.page[shinku_fps_indicator_page].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride)\r
+//     for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);\r
+       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */\r
+//     vga_restore_rm0wm0();\r
+       if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second))\r
+       {\r
+               sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv));\r
+               //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45);\r
+               modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee);\r
+               gv->kurokku.tiku=0;\r
+               /* block copy to visible RAM from offscreen */\r
+//             vga_setup_wm1_block_copy();\r
+//             o =     *(gv->video.page[shinku_fps_indicator_page].data); // source offscreen\r
+//             o2 =    *(gv->video.page[2].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride)\r
+//             for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);\r
+//             modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x, 0, w, h);\r
+               /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */\r
+//             vga_restore_rm0wm0();\r
+       }else //copy dat sheet\r
+       gv->kurokku.tiku++;\r
+\r
+       switch(gv->kurokku.fpscap)\r
+       {\r
+               case 0:\r
+                       //modexprint(&(gv->video.page[shinku_fps_indicator_page]), x, y+8, type, col, bgcol, "sanic!");\r
+                       gv->kurokku.frames_per_second=1;\r
+               break;\r
+               case 1:\r
+                       //turn this off if XT\r
+                       //modexWaitBorder();\r
+                       vga_wait_for_vsync();\r
+                       gv->kurokku.frames_per_second=60;\r
+               break;\r
+       }\r
+       if(pageflipflop){\r
+       if(gv->video.r){\r
+               //vga_setup_wm1_block_copy();\r
+               //_fmemcpy((gv->video.page[(gv->video.p)]).data, (gv->video.page[(!gv->video.p)]).data, gv->video.page[(!gv->video.p)].pagesize);\r
+               //vga_restore_rm0wm0();\r
+               if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height);\r
+               modexShowPage(&(gv->video.page[gv->video.p]));\r
+               if(!pageploop) gv->video.p=!gv->video.p;\r
+               gv->video.r=!gv->video.r;\r
+               //0000gv->video.tickclk = ((*clockw)-gv->video.startclk)/18.2;\r
+       }\r
+       }\r
+}\r
+\r
+void near animatePlayer(map_view_t *pip, player_t *player, word pn, sword scrollswitch)\r
+{\r
+       sword x = player[pn].x;\r
+       sword y = player[pn].y;\r
+       sword bx = x+16;        //buffer's x\r
+       sword by = y+16;        //buffer's y\r
+       word dire=32; //direction\r
+       sword qq; //scroll offset\r
+       word ls = player[pn].persist_aniframe;\r
+\r
+       switch(scrollswitch)\r
+       {\r
+               case 0:\r
+                       qq = 0;\r
+               break;\r
+               default:\r
+                       qq = ((player[pn].q)*(player[pn].speed));\r
+               break;\r
+       }\r
+       //x-=4;\r
+       y-=pip[0].map->tiles->tileHeight;\r
+       switch (player[pn].d)\r
+       {\r
+               case 0:\r
+                       //up\r
+                       dire*=player[pn].d;\r
+                       y-=qq;\r
+                       by-=4;\r
+               break;\r
+               case 3:\r
+                       // right\r
+                       dire*=(player[pn].d-2);\r
+                       x+=qq;\r
+                       bx+=4;\r
+               break;\r
+               case 2:\r
+               break;\r
+               case 4:\r
+                       //down\r
+                       dire*=(player[pn].d-2);\r
+                       y+=qq;\r
+                       by+=4;\r
+               break;\r
+               case 1:\r
+                       //left\r
+                       dire*=(player[pn].d+2);\r
+                       x-=qq;\r
+                       bx-=4;\r
+               break;\r
+       }\r
+\r
+#ifdef SPRITE\r
+//#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 32, dire, 16, 32,      PLAYERBMPDATA);\r
+//#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 16, dire, 16, 32,      PLAYERBMPDATA);\r
+//#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 16, 32,       PLAYERBMPDATA);\r
+//#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 16, dire, 16, 32,      PLAYERBMPDATA);\r
+#define FRAME1 animate_spri(player[pn].spri);\r
+#define FRAME2 animate_spri(player[pn].spri);\r
+#define FRAME3 animate_spri(player[pn].spri);\r
+#define FRAME4 animate_spri(player[pn].spri);\r
+#else\r
+#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 2+dire);\r
+#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 1+dire);\r
+#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, dire);\r
+#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 1+dire);\r
+#endif\r
+       if(!pageflipflop)\r
+               modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 36);\r
+       else{\r
+               //copy old bg to page0\r
+               //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0,   20, 36);\r
+               //update buffer\r
+               //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0,   x, y,   20, 36);\r
+       }\r
+//modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height);\r
+       //modexCopyPageRegion(pip[3].page, pip[!(pip->video->p)].page, x-4, y-4, 0, 128, 28, 36);\r
+       /*modexCopyPageRegion(pip[pip->video->p].page,\r
+ pip[!(pip->video->p)].page, x-4, y-4, x-4, y-4, 28, 36);*/\r
+//     else modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 40);\r
+       switch(ls)\r
+       {\r
+               case 1:\r
+                       FRAME1\r
+               break;\r
+               case 2:\r
+                       FRAME2\r
+               break;\r
+               case 3:\r
+                       FRAME3\r
+               break;\r
+               case 4:\r
+                       FRAME4\r
+               break;\r
+       }\r
+//     if(2>ls && ls>=1) { FRAME1 }else\r
+//     if(3>ls && ls>=2) { FRAME2 }else\r
+//     if(4>ls && ls>=3) { FRAME3 }else\r
+//     if(5>ls && ls>=4) { FRAME4 }\r
+       //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 16, 32);\r
+       //printf("x=%d  y=%d    bx=%d           by=%d\n", x, y, bx, by);\r
+       pip->video->r=1;\r
+}\r
index 3f8ab3e51b28c1f8fbbed1601e838b154fee7773..ee209e361eb3a5897e72c2933877d4546558d488 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "src/lib/bakapee.h"
-
-/* clrstdin() clear any leftover chars tha may be in stdin stream */
-void clrstdin()
-{
-   int ch = 0;
-   while( ( ch = getchar() ) != '\n' && ch != EOF );
-}
-
-//color \82Ä\82·\82Æ
-void colortest(page_t *page, bakapee_t *pee)
-{
-       //if(pee->coor < 256)
-       //{
-               modexcls(page, pee->coor, VGA);
-               pee->coor++;
-       //}else pee->coor = 0;
-}
-
-//color \82Ä\82·\82Æ
-void colorz(page_t *page, bakapee_t *pee)
-{
-       if(pee->coor <= HGQ)
-       {
-               modexcls(page, pee->coor, VGA);
-               pee->coor++;
-       }else pee->coor = LGQ;
-}
-
-//slow spectrum down
-void ssd(page_t *page, bakapee_t *pee, word svq)
-{
-       if(pee->sy < page->sh+1)
-       {
-               if(pee->sx < page->sw+1)
-               {
-                       //mxPutPixel(sx, sy, coor);
-                       //printf("%d %d %d %d\n", pee->sx, pee->sy, svq, pee->coor);
-                       dingpp(page, pee);
-                       pee->sx++;
-               }else pee->sx = 0;
-               if(pee->sx == page->sw)
-               {
-                       pee->sy++;
-                       if(svq == 7) pee->coor++;
-                       if(pee->sy == page->sh && svq == 8) pee->coor = rand()%256;
-               }
-       }else pee->sy = 0;
-}
-
-//plot pixel or plot tile
-void dingpp(page_t *page, bakapee_t *pee)
-{
-       if(pee->tile)
-       {
-#ifndef MXLIB
-       //fill_block(pee->xx, pee->yy, pee->xx+TILEWH, pee->yy+TILEWH, pee->coor);
-               mxFillBox(pee->xx, pee->yy, TILEWH, TILEWH, pee->coor, OP_SET);
-#else
-               modexClearRegion(page, pee->xx, pee->yy, TILEWH, TILEWH, pee->coor);
-#endif
-       }
-       else
-               modexputPixel(page, pee->xx, pee->yy, pee->coor);
-}
-
-void dingo(page_t *page, bakapee_t *pee)
-{
-       if(pee->tile)
-       {
-               if(pee->xx<0) pee->xx=(page->sw-TILEWH);
-               if(pee->yy<0) pee->yy=(page->sh-TILEWH);
-               if(pee->xx>(page->sw-TILEWH)) pee->xx=0;
-               if(pee->yy>(page->sh-TILEWH)/*+(TILEWH*BUFFMX)*/) pee->yy=0;
-       }
-               else
-       {
-               if(pee->xx<0) pee->xx=page->sw;
-               if(pee->yy<0) pee->yy=page->sh;
-               if(pee->xx>page->sw) pee->xx=0;
-               if(pee->yy>page->sh) pee->yy=0;
-       }
-}
-
-//assigning values from randomizer
-void dingas(bakapee_t *pee)
-{
-       if(pee->gq == BONK) dingu(pee);
-       if(!pee->bakax)
-       {
-               if(pee->tile)
-               pee->xx-=TILEWH;
-               else pee->xx--;
-       }
-       else if(pee->bakax>1)
-       {
-               if(pee->tile)
-               pee->xx+=TILEWH;
-               else pee->xx++;
-       }
-       if(!pee->bakay)
-       {
-               if(pee->tile)
-               pee->yy-=TILEWH;
-               else pee->yy--;
-       }
-       else if(pee->bakay>1)
-       {
-               if(pee->tile)
-               pee->yy+=TILEWH;
-               else pee->yy++;
-       }
-}
-
-void dingu(bakapee_t *pee)
-{
-       if(pee->coor < HGQ && pee->coor < LGQ) pee->coor = LGQ;
-       if(pee->coor < HGQ)
-       {
-               pee->coor++;
-       }else{
-               pee->coor = LGQ;
-       }
-}
-
-//randomizer
-void dingq(bakapee_t *pee)
-{
-       if(pee->gq<BONK)
-       {
-               pee->gq++;
-       }
-       else
-       {
-               dingu(pee);
-               pee->gq = 0;
-       }
-       pee->bakax = rand()%3; pee->bakay = rand()%3;
-}
-
-/*-----------ding-------------*/
-void ding(page_t *page, bakapee_t *pee, word q)
-{
-       word d3y, tx=0,ty=0;
-
-//++++  if(q <= 4 && q!=2 && gq == BONK-1) coor = rand()%HGQ;
-       switch(q)
-       {
-               case 1:
-                       dingq(pee);
-                       if(pee->xx==page->sw){pee->bakax=0;}
-                       if(pee->xx==0){pee->bakax=1;}
-                       if(pee->yy==page->sh){pee->bakay=0;}
-                       if(pee->yy==0){pee->bakay=1;}
-               break;
-               case 2:
-                       dingq(pee);
-                       dingas(pee);
-                       dingo(page, pee);
-                       dingpp(page, pee);      //plot the pixel/tile
-                       if(pee->tile)
-                       modexClearRegion(page, (rand()*TILEWH)%page->width, (rand()*TILEWH)%(page->height), TILEWH, TILEWH, 0);
-                       else
-                       modexputPixel(page, rand()%page->width, rand()%page->height, 0);
-               break;
-               case 3:
-                       dingq(pee);
-                       if(pee->xx!=page->sw||pee->yy!=page->sh)
-                       {
-                               if(pee->xx==0){pee->bakax=1;pee->bakay=-1;d3y=1;}
-                               if(pee->yy==0){pee->bakax=1;pee->bakay=0;d3y=1;}
-                               if(pee->xx==page->sw){pee->bakax=-1;pee->bakay=-1;d3y=1;}
-                               if(pee->yy==page->sh){pee->bakax=1;pee->bakay=0;d3y=1;}
-                       }else if(pee->xx==page->sw&&pee->yy==page->sh) pee->xx=pee->yy=0;
-                       if(d3y)
-                       {
-                               if(pee->bakay<0)
-                               {
-                                       pee->yy--;
-                                       d3y--;
-                               }else
-                               if(pee->bakay>0)
-                               {
-                                       pee->yy++;
-                                       d3y--;
-                               }
-                       }
-                       if(pee->bakax<0)
-                       {
-                               pee->xx--;
-                       }else
-                       if(pee->bakax>0)
-                       {
-                               pee->xx++;
-                       }
-                       dingpp(page, pee);      //plot the pixel/tile
-               break;
-               case 4:
-                       dingq(pee);
-                       dingas(pee);
-                       dingo(page, pee);
-                       dingpp(page, pee);      //plot the pixel/tile
-               break;
-               case 5:
-                       colortest(page, pee);
-               break;
-               case 6:
-                       pee->coor = rand()%256;
-                       modexcls(page, pee->coor, VGA);
-               break;
-               case 7:
-                       if(pee->coor <= HGQ)
-                       {
-                               ssd(page, pee, q);
-                               pee->coor++;
-                       }else pee->coor = LGQ;
-               break;
-               case 8:
-                       colorz(page, pee);
-                       modexprint(page, page->sw/2, page->sh/2, 1, 47, 0, "bakapi");
-               break;
-               case 9:
-                       if(pee->coor <= HGQ)
-                       {
-                               ssd(page, pee, q);
-                               pee->coor++;
-                       }else pee->coor = LGQ;
-               break;
-               case 10:
-                       ssd(page, pee, q); /*printf("%d\n", pee->coor);*/
-               break;
-               case 11:
-                       colorz(page, pee); delay(100);
-               break;
-
-               case 16:        //interesting effects
-                       dingq(pee);
-                       if(!pee->bakax){ pee->xx--;}
-                       else if(pee->bakax>0){ pee->xx++; }
-                       if(!pee->bakay){ pee->yy--;}
-                       else if(pee->bakay>0){ pee->yy++; }
-                       dingas(pee);
-                       tx+=pee->xx+TILEWH+4;
-                       ty+=pee->yy+TILEWH+4;
-                       modexClearRegion(page, tx, ty, 4, 4, pee->coor);
-                       if(pee->tile)
-                       modexClearRegion(page, (rand()*4)%page->width, (rand()*4)%(page->height), 4, 4, 0);
-                       else
-                       modexputPixel(page, rand()%page->width, rand()%(page->height), 0);
-                       //printf("%d %d %d %d %d %d\n", pee->xx, pee->yy, tx, ty, TILEWH);
-               break;
-               default:
-               break;
-       }
-       //pee->coor++;
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "src/lib/bakapee.h"\r
+\r
+/* clrstdin() clear any leftover chars tha may be in stdin stream */\r
+void clrstdin()\r
+{\r
+   int ch = 0;\r
+   while( ( ch = getchar() ) != '\n' && ch != EOF );\r
+}\r
+\r
+//color \82Ä\82·\82Æ\r
+void colortest(page_t *page, bakapee_t *pee)\r
+{\r
+       //if(pee->coor < 256)\r
+       //{\r
+               modexcls(page, pee->coor, VGA);\r
+               pee->coor++;\r
+       //}else pee->coor = 0;\r
+}\r
+\r
+//color \82Ä\82·\82Æ\r
+void colorz(page_t *page, bakapee_t *pee)\r
+{\r
+       if(pee->coor <= HGQ)\r
+       {\r
+               modexcls(page, pee->coor, VGA);\r
+               pee->coor++;\r
+       }else pee->coor = LGQ;\r
+}\r
+\r
+//slow spectrum down\r
+void ssd(page_t *page, bakapee_t *pee, word svq)\r
+{\r
+       if(pee->sy < page->sh+1)\r
+       {\r
+               if(pee->sx < page->sw+1)\r
+               {\r
+                       //mxPutPixel(sx, sy, coor);\r
+                       //printf("%d %d %d %d\n", pee->sx, pee->sy, svq, pee->coor);\r
+                       dingpp(page, pee);\r
+                       pee->sx++;\r
+               }else pee->sx = 0;\r
+               if(pee->sx == page->sw)\r
+               {\r
+                       pee->sy++;\r
+                       if(svq == 7) pee->coor++;\r
+                       if(pee->sy == page->sh && svq == 8) pee->coor = rand()%256;\r
+               }\r
+       }else pee->sy = 0;\r
+}\r
+\r
+//plot pixel or plot tile\r
+void dingpp(page_t *page, bakapee_t *pee)\r
+{\r
+       if(pee->tile)\r
+       {\r
+#ifndef MXLIB\r
+       //fill_block(pee->xx, pee->yy, pee->xx+TILEWH, pee->yy+TILEWH, pee->coor);\r
+               mxFillBox(pee->xx, pee->yy, TILEWH, TILEWH, pee->coor, OP_SET);\r
+#else\r
+               modexClearRegion(page, pee->xx, pee->yy, TILEWH, TILEWH, pee->coor);\r
+#endif\r
+       }\r
+       else\r
+               modexputPixel(page, pee->xx, pee->yy, pee->coor);\r
+}\r
+\r
+void dingo(page_t *page, bakapee_t *pee)\r
+{\r
+       if(pee->tile)\r
+       {\r
+               if(pee->xx<0) pee->xx=(page->sw-TILEWH);\r
+               if(pee->yy<0) pee->yy=(page->sh-TILEWH);\r
+               if(pee->xx>(page->sw-TILEWH)) pee->xx=0;\r
+               if(pee->yy>(page->sh-TILEWH)/*+(TILEWH*BUFFMX)*/) pee->yy=0;\r
+       }\r
+               else\r
+       {\r
+               if(pee->xx<0) pee->xx=page->sw;\r
+               if(pee->yy<0) pee->yy=page->sh;\r
+               if(pee->xx>page->sw) pee->xx=0;\r
+               if(pee->yy>page->sh) pee->yy=0;\r
+       }\r
+}\r
+\r
+//assigning values from randomizer\r
+void dingas(bakapee_t *pee)\r
+{\r
+       if(pee->gq == BONK) dingu(pee);\r
+       if(!pee->bakax)\r
+       {\r
+               if(pee->tile)\r
+               pee->xx-=TILEWH;\r
+               else pee->xx--;\r
+       }\r
+       else if(pee->bakax>1)\r
+       {\r
+               if(pee->tile)\r
+               pee->xx+=TILEWH;\r
+               else pee->xx++;\r
+       }\r
+       if(!pee->bakay)\r
+       {\r
+               if(pee->tile)\r
+               pee->yy-=TILEWH;\r
+               else pee->yy--;\r
+       }\r
+       else if(pee->bakay>1)\r
+       {\r
+               if(pee->tile)\r
+               pee->yy+=TILEWH;\r
+               else pee->yy++;\r
+       }\r
+}\r
+\r
+void dingu(bakapee_t *pee)\r
+{\r
+       if(pee->coor < HGQ && pee->coor < LGQ) pee->coor = LGQ;\r
+       if(pee->coor < HGQ)\r
+       {\r
+               pee->coor++;\r
+       }else{\r
+               pee->coor = LGQ;\r
+       }\r
+}\r
+\r
+//randomizer\r
+void dingq(bakapee_t *pee)\r
+{\r
+       if(pee->gq<BONK)\r
+       {\r
+               pee->gq++;\r
+       }\r
+       else\r
+       {\r
+               dingu(pee);\r
+               pee->gq = 0;\r
+       }\r
+       pee->bakax = rand()%3; pee->bakay = rand()%3;\r
+}\r
+\r
+/*-----------ding-------------*/\r
+void ding(page_t *page, bakapee_t *pee, word q)\r
+{\r
+       word d3y, tx=0,ty=0;\r
+\r
+//++++  if(q <= 4 && q!=2 && gq == BONK-1) coor = rand()%HGQ;\r
+       switch(q)\r
+       {\r
+               case 1:\r
+                       dingq(pee);\r
+                       if(pee->xx==page->sw){pee->bakax=0;}\r
+                       if(pee->xx==0){pee->bakax=1;}\r
+                       if(pee->yy==page->sh){pee->bakay=0;}\r
+                       if(pee->yy==0){pee->bakay=1;}\r
+               break;\r
+               case 2:\r
+                       dingq(pee);\r
+                       dingas(pee);\r
+                       dingo(page, pee);\r
+                       dingpp(page, pee);      //plot the pixel/tile\r
+                       if(pee->tile)\r
+                       modexClearRegion(page, (rand()*TILEWH)%page->width, (rand()*TILEWH)%(page->height), TILEWH, TILEWH, 0);\r
+                       else\r
+                       modexputPixel(page, rand()%page->width, rand()%page->height, 0);\r
+               break;\r
+               case 3:\r
+                       dingq(pee);\r
+                       if(pee->xx!=page->sw||pee->yy!=page->sh)\r
+                       {\r
+                               if(pee->xx==0){pee->bakax=1;pee->bakay=-1;d3y=1;}\r
+                               if(pee->yy==0){pee->bakax=1;pee->bakay=0;d3y=1;}\r
+                               if(pee->xx==page->sw){pee->bakax=-1;pee->bakay=-1;d3y=1;}\r
+                               if(pee->yy==page->sh){pee->bakax=1;pee->bakay=0;d3y=1;}\r
+                       }else if(pee->xx==page->sw&&pee->yy==page->sh) pee->xx=pee->yy=0;\r
+                       if(d3y)\r
+                       {\r
+                               if(pee->bakay<0)\r
+                               {\r
+                                       pee->yy--;\r
+                                       d3y--;\r
+                               }else\r
+                               if(pee->bakay>0)\r
+                               {\r
+                                       pee->yy++;\r
+                                       d3y--;\r
+                               }\r
+                       }\r
+                       if(pee->bakax<0)\r
+                       {\r
+                               pee->xx--;\r
+                       }else\r
+                       if(pee->bakax>0)\r
+                       {\r
+                               pee->xx++;\r
+                       }\r
+                       dingpp(page, pee);      //plot the pixel/tile\r
+               break;\r
+               case 4:\r
+                       dingq(pee);\r
+                       dingas(pee);\r
+                       dingo(page, pee);\r
+                       dingpp(page, pee);      //plot the pixel/tile\r
+               break;\r
+               case 5:\r
+                       colortest(page, pee);\r
+               break;\r
+               case 6:\r
+                       pee->coor = rand()%256;\r
+                       modexcls(page, pee->coor, VGA);\r
+               break;\r
+               case 7:\r
+                       if(pee->coor <= HGQ)\r
+                       {\r
+                               ssd(page, pee, q);\r
+                               pee->coor++;\r
+                       }else pee->coor = LGQ;\r
+               break;\r
+               case 8:\r
+                       colorz(page, pee);\r
+                       modexprint(page, page->sw/2, page->sh/2, 1, 47, 0, "bakapi");\r
+               break;\r
+               case 9:\r
+                       if(pee->coor <= HGQ)\r
+                       {\r
+                               ssd(page, pee, q);\r
+                               pee->coor++;\r
+                       }else pee->coor = LGQ;\r
+               break;\r
+               case 10:\r
+                       ssd(page, pee, q); /*printf("%d\n", pee->coor);*/\r
+               break;\r
+               case 11:\r
+                       colorz(page, pee); delay(100);\r
+               break;\r
+\r
+               case 16:        //interesting effects\r
+                       dingq(pee);\r
+                       if(!pee->bakax){ pee->xx--;}\r
+                       else if(pee->bakax>0){ pee->xx++; }\r
+                       if(!pee->bakay){ pee->yy--;}\r
+                       else if(pee->bakay>0){ pee->yy++; }\r
+                       dingas(pee);\r
+                       tx+=pee->xx+TILEWH+4;\r
+                       ty+=pee->yy+TILEWH+4;\r
+                       modexClearRegion(page, tx, ty, 4, 4, pee->coor);\r
+                       if(pee->tile)\r
+                       modexClearRegion(page, (rand()*4)%page->width, (rand()*4)%(page->height), 4, 4, 0);\r
+                       else\r
+                       modexputPixel(page, rand()%page->width, rand()%(page->height), 0);\r
+                       //printf("%d %d %d %d %d %d\n", pee->xx, pee->yy, tx, ty, TILEWH);\r
+               break;\r
+               default:\r
+               break;\r
+       }\r
+       //pee->coor++;\r
+}\r
index 9d371053163e67e8049bde8e0b4bbc33c7bf10ce..4bbfefd6b4ac880a4246c11e0bd8ec2c0dafe45d 100755 (executable)
@@ -1,5 +1,5 @@
-/*
-
+/*\r
+\r
                    THE IBM PC PROGRAMMER'S GUIDE TO C\r
                                     \r
                                     \r
@@ -21,8 +21,8 @@ proviso that credit is given to the author. Sections of this work may be
 used and distributed without payment under the proviso that credit is\r
 given to both this work and the author. Source code occuring in this work\r
 may be used within commercial and non-commercial applications without\r
-charge and without reference to the author.
-*/
+charge and without reference to the author.\r
+*/\r
      /*\r
      Various functions for using Expanded memory\r
      */\r
@@ -178,4 +178,4 @@ charge and without reference to the author.
           regs.x.dx = handle;\r
           int86(EMM,&regs,&regs);\r
           return (regs.h.ah == 0);\r
-     }
+     }\r
index b288a548ac6a70cca3f29d616e5aeeb023413257..33d24d06ad7de53f264bcfd1c3f90dd984336073 100755 (executable)
@@ -1,5 +1,5 @@
-/*
-
+/*\r
+\r
                    THE IBM PC PROGRAMMER'S GUIDE TO C\r
                                     \r
                                     \r
@@ -21,24 +21,24 @@ proviso that credit is given to the author. Sections of this work may be
 used and distributed without payment under the proviso that credit is\r
 given to both this work and the author. Source code occuring in this work\r
 may be used within commercial and non-commercial applications without\r
-charge and without reference to the author.
- */
-
-#ifndef __EMS_H_
-#define __EMS_H_
-
+charge and without reference to the author.\r
+ */\r
+\r
+#ifndef __EMS_H_\r
+#define __EMS_H_\r
+\r
 #include <dos.h>\r
 #define   EMM  0x67\r
      \r
-char far *emmbase;
-
-emmtest();
-emmok();
-long emmavail();
-long emmalloc(int n);
-emmmap(long handle, int phys, int page);
-void emmmove(int page, char *str, int n);
-void emmget(int page, char *str, int n);
-emmclose(long handle);
-
-#endif __EMS_H_
+char far *emmbase;\r
+\r
+emmtest();\r
+emmok();\r
+long emmavail();\r
+long emmalloc(int n);\r
+emmmap(long handle, int phys, int page);\r
+void emmmove(int page, char *str, int n);\r
+void emmget(int page, char *str, int n);\r
+emmclose(long handle);\r
+\r
+#endif __EMS_H_\r
index 6021415cc75e7922d45b12935f56348b064d8a7f..1682c32e9ae5990ddd0f0e907270a0f6dde5cbe9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 6021415cc75e7922d45b12935f56348b064d8a7f
+Subproject commit 1682c32e9ae5990ddd0f0e907270a0f6dde5cbe9
index 8a8d5d87396c62a3eff362fd3036459522949446..5421d9dd8a57cf37a23cbdc42006859b24117b06 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "src/lib/mapread.h"
-
-int jsoneq(const char *json, jsmntok_t *tok, const char *s) {
-       if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
-                       strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
-               return 0;
-       }
-       return -1;
-}
-
-//this function is quite messy ^^; sorry! it is a quick and dirty fix~
-word dump(const char *js, jsmntok_t *t, size_t count, word indent, char *js_sv, map_t *map, dword q) {
-       dword i;
-       word j;//, k;
-       bitmap_t bp;
-       #ifdef DEBUG_JS
-       if(indent==0)
-       {
-               fprintf(stdout, "%s\n", js);
-               fprintf(stdout, "\n");
-       }
-       #endif
-       #ifdef DEBUG_DUMPVARS
-       fprintf(stdout, "t->size=[%d]   ", t->size);
-       fprintf(stdout, "q=[%d] ", q);
-       fprintf(stdout, "indent= [%d]   ", indent);
-       fprintf(stdout, "js_sv= [%s]\n", js_sv);
-       #endif
-       if (count == 0) {
-               return 0;
-       }
-       /* We may want to do strtol() here to get numeric value */
-//0000fprintf(stderr, "t->type=%d\n", t->type);
-       if (t->type == JSMN_PRIMITIVE) {
-               if(strstr(js_sv, "data"))
-               {
-                       /*
-                               here we should recursivly call dump again here to skip over the array until we get the facking width of the map.
-                               so we can initiate the map which allocates the facking map->tiles->data->data properly and THEN we can return
-                               here to read the data.... That is my design for this... wwww
-
-                               FUCK well i am stuck.... wwww
-                       */
-                       map->data[q] = (byte)atoi(js+t->start);
-                       #ifdef DEBUG_MAPDATA
-                               fprintf(stdout, "%d[%d]", q, map->data[q]);
-                       #endif
-               }
-               else
-               if(strstr(js_sv, "height"))
-               {
-                       map->height = atoi(js+t->start);
-                       #ifdef DEBUG_MAPVAR
-                       fprintf(stdout, "indent= [%d]   ", indent);
-                       fprintf(stdout, "h:[%d]\n", map->height);
-                       #endif
-               }else if(strstr(js_sv, "width"))
-               {
-                       map->width = atoi(js+t->start);
-                       #ifdef DEBUG_MAPVAR
-                       fprintf(stdout, "indent= [%d]   ", indent);
-                       fprintf(stdout, "w:[%d]\n", map->width);
-                       #endif
-               }
-               return 1;
-               /* We may use strndup() to fetch string value */
-       } else if (t->type == JSMN_STRING) {
-               if(jsoneq(js, t, "data") == 0)
-               {
-//                     fprintf(stdout, "[[[[%d|%d]]]]\n", &(t+1)->size, (t+1)->size);
-//                     fprintf(stdout, "\n%.*s[xx[%d|%d]xx]\n", (t+1)->end - (t+1)->start, js+(t+1)->start, &(t+1)->size, (t+1)->size);
-                       map->data = malloc(sizeof(byte) * (t+1)->size);
-                       map->tiles = malloc(sizeof(tiles_t));
-                       map->tiles->btdata = malloc(sizeof(bitmap_t));
-                       //fix this to be far~
-                       bp = bitmapLoadPcx("data/ed.pcx");
-//                     bp = bitmapLoadPcx("data/koishi^^.pcx");
-                       map->tiles->btdata = &bp;
-//----                 map->tiles->data = planar_buf_from_bitmap(&bp);
-                       //map->tiles->data->data = malloc((16/**2*/)*16);
-                       //map->tiles->data->width = (16/**2*/);
-                       //map->tiles->data->height= 16;
-                       map->tiles->tileHeight = 16;
-                       map->tiles->tileWidth = 16;
-                       map->tiles->rows = 1;
-                       map->tiles->cols = 1;
-                       map->tiles->debug_text=false;
-                       strcpy(js_sv, "data");//strdup(js+t->start);//, t->end - t->start);
-               }
-               else
-               if (jsoneq(js, t, "height") == 0 && indent<=1)
-               {
-                       strcpy(js_sv, "height");//strdup(js+t->start);//, t->end - t->start);
-               }else
-               if(jsoneq(js, t, "width") == 0 && indent<=1)
-               {
-                       strcpy(js_sv, "width");//strdup(js+t->start);//, t->end - t->start);
-               }else strcpy(js_sv, "\0");
-               return 1;
-       } else if (t->type == JSMN_OBJECT) {
-               //fprintf(stdout, "\n");
-               j = 0;
-               for (i = 0; i < t->size; i++) {
-                       //for (k = 0; k < indent; k++) fprintf(stdout, "\t");
-                       j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i);
-                       //fprintf(stdout, ": ");
-                       j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i);
-                       //fprintf(stdout, "\n");
-               }
-               return j+1;
-       } else if (t->type == JSMN_ARRAY) {
-               j = 0;
-               //fprintf(stdout, "==\n");
-               for (i = 0; i < t->size; i++) {
-                       //for (k = 0; k < indent-1; k++) fprintf(stdout, "\t");
-                       //fprintf(stdout, "\t-");
-                       j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i);
-                       //fprintf(stdout, "==\n");
-               }
-               return j+1;
-       }
-       return 0;
-}
-
-int loadmap(char *mn, map_t *map)
-{
-       int r;
-       static word incr=0;
-       int eof_expected = 0;
-       char *js = NULL;
-       size_t jslen = 0;
-       char buf[BUFSIZ];
-       static char js_ss[16];
-
-       jsmn_parser p;
-       jsmntok_t *tok;
-       size_t tokcount = 2;
-
-       FILE *fh = fopen(mn, "r");
-
-       /* Prepare parser */
-       jsmn_init(&p);
-
-       /* Allocate some tokens as a start */
-//0000fprintf(stderr, "tok malloc\n");
-       tok = malloc(sizeof(*tok) * tokcount);
-       if (tok == NULL) {
-               fprintf(stderr, "malloc(): errno=%d\n", errno);
-               return 3;
-       }
-
-       for (;;) {
-               /* Read another chunk */
-//0000fprintf(stderr, "read\n");
-               r = fread(buf, 1, sizeof(buf), fh);
-               if (r < 0) {
-                       fprintf(stderr, "fread(): %d, errno=%d\n", r, errno);
-                       return 1;
-               }
-               if (r == 0) {
-                       if (eof_expected != 0) {
-                               return 0;
-                       } else {
-                               fprintf(stderr, "fread(): unexpected EOF\n");
-                               return 2;
-                       }
-               }
-//0000fprintf(stdout, "r=      [%d]    BUFSIZ=%d\n", r, BUFSIZ);
-//0000fprintf(stderr, "js alloc~\n");
-               js = realloc(js, jslen + r + 1);
-               if (js == NULL) {
-                       fprintf(stderr, "*js=%Fp\n", *js);
-                       fprintf(stderr, "realloc(): errno = %d\n", errno);
-                       return 3;
-               }
-               strncpy(js + jslen, buf, r);
-               jslen = jslen + r;
-
-again:
-//0000fprintf(stdout, "        parse~ tok=%zu  jslen=%zu       r=%d    _memavl()=%u    BUFSIZ=%d~\n", tokcount, jslen, r, _memavl(), BUFSIZ);
-//0000fprintf(stdout, "p=[%u]  [%u]    [%d]\n", p.pos, p.toknext, p.toksuper);
-/*
-               I think it crashes on the line below when it tries to parse the data of huge maps... wwww this is a jsmn problem wwww
-*/
-               r = jsmn_parse(&p, js, jslen, tok, tokcount);
-//0000fprintf(stdout, "r=      [%d]\n", r);
-               if (r < 0) {
-                       if (r == JSMN_ERROR_NOMEM) {
-                               tokcount = tokcount * 2;
-//0000fprintf(stderr, "tok realloc~ %zu\n", tokcount);
-                               tok = realloc(tok, sizeof(*tok) * tokcount);
-                               if (tok == NULL) {
-                                       fprintf(stderr, "realloc(): errno=%d\n", errno);
-                                       return 3;
-                               }
-                               goto again;
-                       }
-               } else {
-                       //printf("js=%Fp\n", (js));
-                       //printf("*js=%Fp\n", (*(js)));
-                       //printf("&*js=%s\n", &(*(js)));
-                       //printf("&buf=[%Fp]\n", &buf);
-                       //printf("&buf_seg=[%x]\n", FP_SEG(&buf));
-                       //printf("&buf_off=[%x]\n", FP_OFF(&buf));
-                       //printf("&buf_fp=[%Fp]\n", MK_FP(FP_SEG(&buf), FP_OFF(&buf)));
-                       //printf("buf=[\n%s\n]\n", buf);
-                       //printf("buff=[%Fp]\n", buff);
-                       //printf("(*buff)=[%Fp]\n", (*buff));
-                       //printf("&(*buff)=[\n%s\n]\n", &(*buff));
-                       #ifdef DEBUG_DUMPVARS
-                       fprintf(stdout, "running dump~\n");
-                       #endif
-                       dump(js, tok, p.toknext, incr, &js_ss, map, 0);
-                       eof_expected = 1;
-               }
-       }
-
-       free(js);
-       free(tok);
-       fclose(fh);
-
-       return 0;
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "src/lib/mapread.h"\r
+\r
+int jsoneq(const char *json, jsmntok_t *tok, const char *s) {\r
+       if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&\r
+                       strncmp(json + tok->start, s, tok->end - tok->start) == 0) {\r
+               return 0;\r
+       }\r
+       return -1;\r
+}\r
+\r
+//this function is quite messy ^^; sorry! it is a quick and dirty fix~\r
+word dump(const char *js, jsmntok_t *t, size_t count, word indent, char *js_sv, map_t *map, dword q) {\r
+       dword i;\r
+       word j;//, k;\r
+       bitmap_t bp;\r
+       #ifdef DEBUG_JS\r
+       if(indent==0)\r
+       {\r
+               fprintf(stdout, "%s\n", js);\r
+               fprintf(stdout, "\n");\r
+       }\r
+       #endif\r
+       #ifdef DEBUG_DUMPVARS\r
+       fprintf(stdout, "t->size=[%d]   ", t->size);\r
+       fprintf(stdout, "q=[%d] ", q);\r
+       fprintf(stdout, "indent= [%d]   ", indent);\r
+       fprintf(stdout, "js_sv= [%s]\n", js_sv);\r
+       #endif\r
+       if (count == 0) {\r
+               return 0;\r
+       }\r
+       /* We may want to do strtol() here to get numeric value */\r
+//0000fprintf(stderr, "t->type=%d\n", t->type);\r
+       if (t->type == JSMN_PRIMITIVE) {\r
+               if(strstr(js_sv, "data"))\r
+               {\r
+                       /*\r
+                               here we should recursivly call dump again here to skip over the array until we get the facking width of the map.\r
+                               so we can initiate the map which allocates the facking map->tiles->data->data properly and THEN we can return\r
+                               here to read the data.... That is my design for this... wwww\r
+\r
+                               FUCK well i am stuck.... wwww\r
+                       */\r
+                       map->data[q] = (byte)atoi(js+t->start);\r
+                       #ifdef DEBUG_MAPDATA\r
+                               fprintf(stdout, "%d[%d]", q, map->data[q]);\r
+                       #endif\r
+               }\r
+               else\r
+               if(strstr(js_sv, "height"))\r
+               {\r
+                       map->height = atoi(js+t->start);\r
+                       #ifdef DEBUG_MAPVAR\r
+                       fprintf(stdout, "indent= [%d]   ", indent);\r
+                       fprintf(stdout, "h:[%d]\n", map->height);\r
+                       #endif\r
+               }else if(strstr(js_sv, "width"))\r
+               {\r
+                       map->width = atoi(js+t->start);\r
+                       #ifdef DEBUG_MAPVAR\r
+                       fprintf(stdout, "indent= [%d]   ", indent);\r
+                       fprintf(stdout, "w:[%d]\n", map->width);\r
+                       #endif\r
+               }\r
+               return 1;\r
+               /* We may use strndup() to fetch string value */\r
+       } else if (t->type == JSMN_STRING) {\r
+               if(jsoneq(js, t, "data") == 0)\r
+               {\r
+//                     fprintf(stdout, "[[[[%d|%d]]]]\n", &(t+1)->size, (t+1)->size);\r
+//                     fprintf(stdout, "\n%.*s[xx[%d|%d]xx]\n", (t+1)->end - (t+1)->start, js+(t+1)->start, &(t+1)->size, (t+1)->size);\r
+                       map->data = malloc(sizeof(byte) * (t+1)->size);\r
+                       map->tiles = malloc(sizeof(tiles_t));\r
+                       map->tiles->btdata = malloc(sizeof(bitmap_t));\r
+                       //fix this to be far~\r
+                       bp = bitmapLoadPcx("data/ed.pcx");\r
+//                     bp = bitmapLoadPcx("data/koishi^^.pcx");\r
+                       map->tiles->btdata = &bp;\r
+//----                 map->tiles->data = planar_buf_from_bitmap(&bp);\r
+                       //map->tiles->data->data = malloc((16/**2*/)*16);\r
+                       //map->tiles->data->width = (16/**2*/);\r
+                       //map->tiles->data->height= 16;\r
+                       map->tiles->tileHeight = 16;\r
+                       map->tiles->tileWidth = 16;\r
+                       map->tiles->rows = 1;\r
+                       map->tiles->cols = 1;\r
+                       map->tiles->debug_text=false;\r
+                       strcpy(js_sv, "data");//strdup(js+t->start);//, t->end - t->start);\r
+               }\r
+               else\r
+               if (jsoneq(js, t, "height") == 0 && indent<=1)\r
+               {\r
+                       strcpy(js_sv, "height");//strdup(js+t->start);//, t->end - t->start);\r
+               }else\r
+               if(jsoneq(js, t, "width") == 0 && indent<=1)\r
+               {\r
+                       strcpy(js_sv, "width");//strdup(js+t->start);//, t->end - t->start);\r
+               }else strcpy(js_sv, "\0");\r
+               return 1;\r
+       } else if (t->type == JSMN_OBJECT) {\r
+               //fprintf(stdout, "\n");\r
+               j = 0;\r
+               for (i = 0; i < t->size; i++) {\r
+                       //for (k = 0; k < indent; k++) fprintf(stdout, "\t");\r
+                       j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i);\r
+                       //fprintf(stdout, ": ");\r
+                       j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i);\r
+                       //fprintf(stdout, "\n");\r
+               }\r
+               return j+1;\r
+       } else if (t->type == JSMN_ARRAY) {\r
+               j = 0;\r
+               //fprintf(stdout, "==\n");\r
+               for (i = 0; i < t->size; i++) {\r
+                       //for (k = 0; k < indent-1; k++) fprintf(stdout, "\t");\r
+                       //fprintf(stdout, "\t-");\r
+                       j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i);\r
+                       //fprintf(stdout, "==\n");\r
+               }\r
+               return j+1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+int loadmap(char *mn, map_t *map)\r
+{\r
+       int r;\r
+       static word incr=0;\r
+       int eof_expected = 0;\r
+       char *js = NULL;\r
+       size_t jslen = 0;\r
+       char buf[BUFSIZ];\r
+       static char js_ss[16];\r
+\r
+       jsmn_parser p;\r
+       jsmntok_t *tok;\r
+       size_t tokcount = 2;\r
+\r
+       FILE *fh = fopen(mn, "r");\r
+\r
+       /* Prepare parser */\r
+       jsmn_init(&p);\r
+\r
+       /* Allocate some tokens as a start */\r
+//0000fprintf(stderr, "tok malloc\n");\r
+       tok = malloc(sizeof(*tok) * tokcount);\r
+       if (tok == NULL) {\r
+               fprintf(stderr, "malloc(): errno=%d\n", errno);\r
+               return 3;\r
+       }\r
+\r
+       for (;;) {\r
+               /* Read another chunk */\r
+//0000fprintf(stderr, "read\n");\r
+               r = fread(buf, 1, sizeof(buf), fh);\r
+               if (r < 0) {\r
+                       fprintf(stderr, "fread(): %d, errno=%d\n", r, errno);\r
+                       return 1;\r
+               }\r
+               if (r == 0) {\r
+                       if (eof_expected != 0) {\r
+                               return 0;\r
+                       } else {\r
+                               fprintf(stderr, "fread(): unexpected EOF\n");\r
+                               return 2;\r
+                       }\r
+               }\r
+//0000fprintf(stdout, "r=      [%d]    BUFSIZ=%d\n", r, BUFSIZ);\r
+//0000fprintf(stderr, "js alloc~\n");\r
+               js = realloc(js, jslen + r + 1);\r
+               if (js == NULL) {\r
+                       fprintf(stderr, "*js=%Fp\n", *js);\r
+                       fprintf(stderr, "realloc(): errno = %d\n", errno);\r
+                       return 3;\r
+               }\r
+               strncpy(js + jslen, buf, r);\r
+               jslen = jslen + r;\r
+\r
+again:\r
+//0000fprintf(stdout, "        parse~ tok=%zu  jslen=%zu       r=%d    _memavl()=%u    BUFSIZ=%d~\n", tokcount, jslen, r, _memavl(), BUFSIZ);\r
+//0000fprintf(stdout, "p=[%u]  [%u]    [%d]\n", p.pos, p.toknext, p.toksuper);\r
+/*\r
+               I think it crashes on the line below when it tries to parse the data of huge maps... wwww this is a jsmn problem wwww\r
+*/\r
+               r = jsmn_parse(&p, js, jslen, tok, tokcount);\r
+//0000fprintf(stdout, "r=      [%d]\n", r);\r
+               if (r < 0) {\r
+                       if (r == JSMN_ERROR_NOMEM) {\r
+                               tokcount = tokcount * 2;\r
+//0000fprintf(stderr, "tok realloc~ %zu\n", tokcount);\r
+                               tok = realloc(tok, sizeof(*tok) * tokcount);\r
+                               if (tok == NULL) {\r
+                                       fprintf(stderr, "realloc(): errno=%d\n", errno);\r
+                                       return 3;\r
+                               }\r
+                               goto again;\r
+                       }\r
+               } else {\r
+                       //printf("js=%Fp\n", (js));\r
+                       //printf("*js=%Fp\n", (*(js)));\r
+                       //printf("&*js=%s\n", &(*(js)));\r
+                       //printf("&buf=[%Fp]\n", &buf);\r
+                       //printf("&buf_seg=[%x]\n", FP_SEG(&buf));\r
+                       //printf("&buf_off=[%x]\n", FP_OFF(&buf));\r
+                       //printf("&buf_fp=[%Fp]\n", MK_FP(FP_SEG(&buf), FP_OFF(&buf)));\r
+                       //printf("buf=[\n%s\n]\n", buf);\r
+                       //printf("buff=[%Fp]\n", buff);\r
+                       //printf("(*buff)=[%Fp]\n", (*buff));\r
+                       //printf("&(*buff)=[\n%s\n]\n", &(*buff));\r
+                       #ifdef DEBUG_DUMPVARS\r
+                       fprintf(stdout, "running dump~\n");\r
+                       #endif\r
+                       dump(js, tok, p.toknext, incr, &js_ss, map, 0);\r
+                       eof_expected = 1;\r
+               }\r
+       }\r
+\r
+       free(js);\r
+       free(tok);\r
+       fclose(fh);\r
+\r
+       return 0;\r
+}\r
index 760906c87681b9c38a28b379a066f7ca6be47c97..7e6ac1c5ac07776ba505f195d72d742b0b9ab3be 100755 (executable)
-/* midi.c
- *
- * Adlib OPL2/OPL3 FM synthesizer chipset test program.
- * Play MIDI file using the OPLx synthesizer (well, poorly anyway)
- * (C) 2010-2012 Jonathan Campbell.
- * Hackipedia DOS library.
- *
- * This code is licensed under the LGPL.
- * <insert LGPL legal text here>
- *
- * Compiles for intended target environments:
- *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]
- */
-
-#include "src/lib/midi.h"
-
-static unsigned int            midi_trk_count=0;
-struct midi_note               midi_notes[ADLIB_FM_VOICES];
-struct midi_channel            midi_ch[MIDI_MAX_CHANNELS];
-struct midi_track              midi_trk[MIDI_MAX_TRACKS];
-
-/* MIDI params. Nobody ever said it was a straightforward standard!
- * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */
-static unsigned int ticks_per_quarter_note=0;  /* "Ticks per beat" */
-
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */
-       return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p));
-}
-#endif
-
-static inline unsigned char midi_trk_read(struct midi_track *t) {
-       unsigned char c;
-
-       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */
-       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) {
-               t->eof = 1;
-               return 0xFF;
-       }
-
-       c = *(t->read);
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-       if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */
-               t->read = MK_FP(FP_SEG(t->read)+0x1,0);
-       else
-               t->read++;
-#else
-       t->read++;
-#endif
-       return c;
-}
-
-void midi_trk_end(struct midi_track *t) {
-       t->wait = ~0UL;
-       t->read = t->fence;
-}
-
-void midi_trk_skip(struct midi_track *t,unsigned long len) {
-       unsigned long rem;
-
-       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */
-       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence)
-               return;
-
-       if (len > 0xFFF0UL) {
-               midi_trk_end(t);
-               return;
-       }
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-       {
-               unsigned long tt;
-
-               tt = farptr2phys(t->read);
-               rem = farptr2phys(t->fence) - tt;
-               if (rem > len) rem = len;
-               tt += rem;
-               t->read = MK_FP(tt>>4,tt&0xF);
-       }
-#else
-       rem = (unsigned long)(t->fence - t->read);
-       if (len > rem) len = rem;
-       t->read += len;
-#endif
-}
-
-static const uint32_t midikeys_freqs[0x80] = {
-       0x00082d01,     /* key 0 = 8.17579891564371Hz */
-       0x0008a976,     /* key 1 = 8.66195721802725Hz */
-       0x00092d51,     /* key 2 = 9.17702399741899Hz */
-       0x0009b904,     /* key 3 = 9.72271824131503Hz */
-       0x000a4d05,     /* key 4 = 10.3008611535272Hz */
-       0x000ae9d3,     /* key 5 = 10.9133822322814Hz */
-       0x000b8ff4,     /* key 6 = 11.5623257097386Hz */
-       0x000c3ff6,     /* key 7 = 12.2498573744297Hz */
-       0x000cfa70,     /* key 8 = 12.9782717993733Hz */
-       0x000dc000,     /* key 9 = 13.75Hz */
-       0x000e914f,     /* key 10 = 14.5676175474403Hz */
-       0x000f6f11,     /* key 11 = 15.4338531642539Hz */
-       0x00105a02,     /* key 12 = 16.3515978312874Hz */
-       0x001152ec,     /* key 13 = 17.3239144360545Hz */
-       0x00125aa2,     /* key 14 = 18.354047994838Hz */
-       0x00137208,     /* key 15 = 19.4454364826301Hz */
-       0x00149a0a,     /* key 16 = 20.6017223070544Hz */
-       0x0015d3a6,     /* key 17 = 21.8267644645627Hz */
-       0x00171fe9,     /* key 18 = 23.1246514194771Hz */
-       0x00187fed,     /* key 19 = 24.4997147488593Hz */
-       0x0019f4e0,     /* key 20 = 25.9565435987466Hz */
-       0x001b8000,     /* key 21 = 27.5Hz */
-       0x001d229e,     /* key 22 = 29.1352350948806Hz */
-       0x001ede22,     /* key 23 = 30.8677063285078Hz */
-       0x0020b404,     /* key 24 = 32.7031956625748Hz */
-       0x0022a5d8,     /* key 25 = 34.647828872109Hz */
-       0x0024b545,     /* key 26 = 36.7080959896759Hz */
-       0x0026e410,     /* key 27 = 38.8908729652601Hz */
-       0x00293414,     /* key 28 = 41.2034446141087Hz */
-       0x002ba74d,     /* key 29 = 43.6535289291255Hz */
-       0x002e3fd2,     /* key 30 = 46.2493028389543Hz */
-       0x0030ffda,     /* key 31 = 48.9994294977187Hz */
-       0x0033e9c0,     /* key 32 = 51.9130871974931Hz */
-       0x00370000,     /* key 33 = 55Hz */
-       0x003a453d,     /* key 34 = 58.2704701897612Hz */
-       0x003dbc44,     /* key 35 = 61.7354126570155Hz */
-       0x00416809,     /* key 36 = 65.4063913251497Hz */
-       0x00454bb0,     /* key 37 = 69.295657744218Hz */
-       0x00496a8b,     /* key 38 = 73.4161919793519Hz */
-       0x004dc820,     /* key 39 = 77.7817459305202Hz */
-       0x00526829,     /* key 40 = 82.4068892282175Hz */
-       0x00574e9b,     /* key 41 = 87.307057858251Hz */
-       0x005c7fa4,     /* key 42 = 92.4986056779086Hz */
-       0x0061ffb5,     /* key 43 = 97.9988589954373Hz */
-       0x0067d380,     /* key 44 = 103.826174394986Hz */
-       0x006e0000,     /* key 45 = 110Hz */
-       0x00748a7b,     /* key 46 = 116.540940379522Hz */
-       0x007b7888,     /* key 47 = 123.470825314031Hz */
-       0x0082d012,     /* key 48 = 130.812782650299Hz */
-       0x008a9760,     /* key 49 = 138.591315488436Hz */
-       0x0092d517,     /* key 50 = 146.832383958704Hz */
-       0x009b9041,     /* key 51 = 155.56349186104Hz */
-       0x00a4d053,     /* key 52 = 164.813778456435Hz */
-       0x00ae9d36,     /* key 53 = 174.614115716502Hz */
-       0x00b8ff49,     /* key 54 = 184.997211355817Hz */
-       0x00c3ff6a,     /* key 55 = 195.997717990875Hz */
-       0x00cfa700,     /* key 56 = 207.652348789973Hz */
-       0x00dc0000,     /* key 57 = 220Hz */
-       0x00e914f6,     /* key 58 = 233.081880759045Hz */
-       0x00f6f110,     /* key 59 = 246.941650628062Hz */
-       0x0105a025,     /* key 60 = 261.625565300599Hz */
-       0x01152ec0,     /* key 61 = 277.182630976872Hz */
-       0x0125aa2e,     /* key 62 = 293.664767917408Hz */
-       0x01372082,     /* key 63 = 311.126983722081Hz */
-       0x0149a0a7,     /* key 64 = 329.62755691287Hz */
-       0x015d3a6d,     /* key 65 = 349.228231433004Hz */
-       0x0171fe92,     /* key 66 = 369.994422711634Hz */
-       0x0187fed4,     /* key 67 = 391.995435981749Hz */
-       0x019f4e00,     /* key 68 = 415.304697579945Hz */
-       0x01b80000,     /* key 69 = 440Hz */
-       0x01d229ec,     /* key 70 = 466.16376151809Hz */
-       0x01ede220,     /* key 71 = 493.883301256124Hz */
-       0x020b404a,     /* key 72 = 523.251130601197Hz */
-       0x022a5d81,     /* key 73 = 554.365261953744Hz */
-       0x024b545c,     /* key 74 = 587.329535834815Hz */
-       0x026e4104,     /* key 75 = 622.253967444162Hz */
-       0x0293414f,     /* key 76 = 659.25511382574Hz */
-       0x02ba74da,     /* key 77 = 698.456462866008Hz */
-       0x02e3fd24,     /* key 78 = 739.988845423269Hz */
-       0x030ffda9,     /* key 79 = 783.990871963499Hz */
-       0x033e9c01,     /* key 80 = 830.60939515989Hz */
-       0x03700000,     /* key 81 = 880Hz */
-       0x03a453d8,     /* key 82 = 932.32752303618Hz */
-       0x03dbc440,     /* key 83 = 987.766602512248Hz */
-       0x04168094,     /* key 84 = 1046.50226120239Hz */
-       0x0454bb03,     /* key 85 = 1108.73052390749Hz */
-       0x0496a8b8,     /* key 86 = 1174.65907166963Hz */
-       0x04dc8208,     /* key 87 = 1244.50793488832Hz */
-       0x0526829e,     /* key 88 = 1318.51022765148Hz */
-       0x0574e9b5,     /* key 89 = 1396.91292573202Hz */
-       0x05c7fa49,     /* key 90 = 1479.97769084654Hz */
-       0x061ffb53,     /* key 91 = 1567.981743927Hz */
-       0x067d3802,     /* key 92 = 1661.21879031978Hz */
-       0x06e00000,     /* key 93 = 1760Hz */
-       0x0748a7b1,     /* key 94 = 1864.65504607236Hz */
-       0x07b78880,     /* key 95 = 1975.5332050245Hz */
-       0x082d0128,     /* key 96 = 2093.00452240479Hz */
-       0x08a97607,     /* key 97 = 2217.46104781498Hz */
-       0x092d5171,     /* key 98 = 2349.31814333926Hz */
-       0x09b90410,     /* key 99 = 2489.01586977665Hz */
-       0x0a4d053c,     /* key 100 = 2637.02045530296Hz */
-       0x0ae9d36b,     /* key 101 = 2793.82585146403Hz */
-       0x0b8ff493,     /* key 102 = 2959.95538169308Hz */
-       0x0c3ff6a7,     /* key 103 = 3135.96348785399Hz */
-       0x0cfa7005,     /* key 104 = 3322.43758063956Hz */
-       0x0dc00000,     /* key 105 = 3520Hz */
-       0x0e914f62,     /* key 106 = 3729.31009214472Hz */
-       0x0f6f1100,     /* key 107 = 3951.06641004899Hz */
-       0x105a0250,     /* key 108 = 4186.00904480958Hz */
-       0x1152ec0e,     /* key 109 = 4434.92209562995Hz */
-       0x125aa2e3,     /* key 110 = 4698.63628667852Hz */
-       0x13720820,     /* key 111 = 4978.03173955329Hz */
-       0x149a0a79,     /* key 112 = 5274.04091060592Hz */
-       0x15d3a6d6,     /* key 113 = 5587.65170292806Hz */
-       0x171fe927,     /* key 114 = 5919.91076338615Hz */
-       0x187fed4e,     /* key 115 = 6271.92697570799Hz */
-       0x19f4e00a,     /* key 116 = 6644.87516127912Hz */
-       0x1b800000,     /* key 117 = 7040Hz */
-       0x1d229ec4,     /* key 118 = 7458.62018428944Hz */
-       0x1ede2200,     /* key 119 = 7902.13282009799Hz */
-       0x20b404a1,     /* key 120 = 8372.01808961916Hz */
-       0x22a5d81c,     /* key 121 = 8869.84419125991Hz */
-       0x24b545c7,     /* key 122 = 9397.27257335704Hz */
-       0x26e41040,     /* key 123 = 9956.06347910659Hz */
-       0x293414f2,     /* key 124 = 10548.0818212118Hz */
-       0x2ba74dac,     /* key 125 = 11175.3034058561Hz */
-       0x2e3fd24f,     /* key 126 = 11839.8215267723Hz */
-       0x30ffda9c      /* key 127 = 12543.853951416Hz */
-};
-
-static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) {
-       return midikeys_freqs[key&0x7F];
-}
-
-static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) {
-       unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */
-       unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */
-       unsigned int i,freen=~0;
-
-       for (i=0;i < ADLIB_FM_VOICES;i++) {
-               if (midi_notes[i].busy) {
-                       if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key)
-                               return &midi_notes[i];
-               }
-               else {
-                       if (freen == ~0) freen = i;
-               }
-       }
-
-       if (do_alloc && freen != ~0) return &midi_notes[freen];
-       return NULL;
-}
-
-static void drop_fm_note(struct midi_channel *ch,unsigned char key) {
-       unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */
-       unsigned int i;
-
-       for (i=0;i < ADLIB_FM_VOICES;i++) {
-               if (midi_notes[i].busy && midi_notes[i].note_channel == ach) {
-                       midi_notes[i].busy = 0;
-                       break;
-               }
-       }
-}
-
-static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {
-       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0);
-       uint32_t freq = midi_note_freq(ch,key);
-       unsigned int ach;
-
-       if (note == NULL) return;
-
-       note->busy = 1;
-       note->note_number = key;
-       note->note_velocity = vel;
-       note->note_track = (unsigned int)(t - midi_trk);
-       note->note_channel = (unsigned int)(ch - midi_ch);
-       ach = (unsigned int)(note - midi_notes); /* which FM channel? */
-       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);
-       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */
-       adlib_fm[ach].mod.sustain_level = vel >> 3;
-       adlib_fm[ach].mod.key_on = 1;
-       adlib_update_groupA0(ach,&adlib_fm[ach]);
-}
-
-static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {
-       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1);
-       uint32_t freq = midi_note_freq(ch,key);
-       unsigned int ach;
-
-       /* HACK: Ignore percussion */
-       if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ ||
-               (ch->program >= 112 && ch->program <= 119)/*Percussive*/ ||
-               ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/)
-               return;
-
-       if (note == NULL) {
-               /* then we'll have to knock one off to make room */
-               drop_fm_note(ch,key);
-               note = get_fm_note(t,ch,key,1);
-               if (note == NULL) return;
-       }
-
-       note->busy = 1;
-       note->note_number = key;
-       note->note_velocity = vel;
-       note->note_track = (unsigned int)(t - midi_trk);
-       note->note_channel = (unsigned int)(ch - midi_ch);
-       ach = (unsigned int)(note - midi_notes); /* which FM channel? */
-       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);
-       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */
-       adlib_fm[ach].mod.sustain_level = vel >> 3;
-       adlib_fm[ach].mod.key_on = 1;
-       adlib_update_groupA0(ach,&adlib_fm[ach]);
-}
-
-static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {
-       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0);
-       uint32_t freq = midi_note_freq(ch,key);
-       unsigned int ach;
-
-       if (note == NULL) return;
-
-       note->busy = 0;
-       ach = (unsigned int)(note - midi_notes); /* which FM channel? */
-       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);
-       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */
-       adlib_fm[ach].mod.sustain_level = vel >> 3;
-       adlib_fm[ach].mod.key_on = 0;
-       adlib_update_groupA0(ach,&adlib_fm[ach]);
-}
-
-static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) {
-}
-
-static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) {
-       ch->program = inst;
-}
-
-static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) {
-}
-
-static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) {
-}
-
-unsigned long midi_trk_read_delta(struct midi_track *t) {
-       unsigned long tc = 0;
-       unsigned char c = 0,b;
-
-       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */
-       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence)
-               return tc;
-
-       while (c < 4) {
-               b = midi_trk_read(t);
-               tc = (tc << 7UL) + (unsigned long)(b&0x7F);
-               if (!(b&0x80)) break;
-               c++;
-       }
-
-       return tc;
-}
-
-void midi_tick_track(unsigned int i) {
-       struct midi_track *t = midi_trk + i;
-       struct midi_channel *ch;
-       unsigned char b,c,d;
-       int cnt=0;
-
-       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */
-       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) {
-               t->eof = 1;
-               return;
-       }
-
-       t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note;
-       while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) {
-               t->us_tick_cnt_mtpq -= t->us_per_quarter_note;
-               cnt++;
-
-               while (t->wait == 0) {
-                       if ((unsigned long)t->read >= (unsigned long)t->fence) {
-                               t->eof = 1;
-                               break;
-                       }
-
-                       /* read pointer should be pointing at MIDI event bytes, just after the time delay */
-                       b = midi_trk_read(t);
-                       if (b&0x80) {
-                               if (b < 0xF8) {
-                                       if (b >= 0xF0)
-                                               t->last_status = 0;
-                                       else
-                                               t->last_status = b;
-                               }
-                               if (b != 0x00 && ((b&0xF8) != 0xF0))
-                                       c = midi_trk_read(t);
-                       }
-                       else {
-                               /* blegh. last status */
-                               c = b;
-                               b = t->last_status;
-                       }
-                       switch (b>>4) {
-                               case 0x8: { /* note off */
-                                       d = midi_trk_read(t);
-                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */
-                                       on_key_off(t,ch,c,d);
-                                       } break;
-                               case 0x9: { /* note on */
-                                       d = midi_trk_read(t);
-                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */
-                                       if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */
-                                       else on_key_off(t,ch,c,d);
-                                       } break;
-                               case 0xA: { /* polyphonic aftertouch */
-                                       d = midi_trk_read(t);
-                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */
-                                       on_key_aftertouch(t,ch,c,d);
-                                       } break;
-                               case 0xB: { /* control change */
-                                       d = midi_trk_read(t);
-                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */
-                                       on_control_change(t,ch,c,d);
-                                       } break;
-                               case 0xC: { /* program change */
-                                       on_program_change(t,ch,c); /* c=instrument d=not used */
-                                       } break;
-                               case 0xD: { /* channel aftertouch */
-                                       on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */
-                                       } break;
-                               case 0xE: { /* pitch bend */
-                                       d = midi_trk_read(t);
-                                       on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */
-                                       } break;
-                               case 0xF: { /* event */
-                                       if (b == 0xFF) {
-                                               if (c == 0x7F) { /* c=type d=len */
-                                                       unsigned long len = midi_trk_read_delta(t);
-//====
-                                                       fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence);
-//====
-                                                       if (len < 512UL) {
-                                                               /* unknown */
-                                                               midi_trk_skip(t,len);
-                                                       }
-                                                       else {
-                                                               midi_trk_end(t);
-                                                       }
-                                               }
-                                               else if (c < 0x7F) {
-                                                       d = midi_trk_read(t);
-
-                                                       if (c == 0x51 && d >= 3) {
-                                                               d -= 3;
-                                                               t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+
-                                                                       ((unsigned long)midi_trk_read(t)<<8UL)+
-                                                                       ((unsigned long)midi_trk_read(t)<<0UL);
-
-                                                               if (1/*TODO: If format 0 or format 1*/) {
-                                                                       /* Ugh. Unless format 2, the tempo applies to all tracks */
-                                                                       int j;
-
-                                                                       for (j=0;j < midi_trk_count;j++) {
-                                                                               if (j != i) midi_trk[j].us_per_quarter_note =
-                                                                                       t->us_per_quarter_note;
-                                                                       }
-                                                               }
-                                                       }
-                                                       else {
-//====
-                                                               fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence);
-//====
-                                                       }
-
-                                                       midi_trk_skip(t,d);
-                                               }
-                                               else {
-                                                       fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence);
-                                               }
-                                       }
-                                       else {
-                                               unsigned long len = midi_trk_read_delta(t);
-//====
-                                               fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence);
-//====
-                                               midi_trk_skip(t,len);
-                                       }
-                                       } break;
-                               default:
-                                       if (b != 0x00) {
-                                               fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence);
-                                               midi_trk_end(t);
-                                       }
-                                       break;
-                       };
-
-                       /* and then read the next event */
-                       t->wait = midi_trk_read_delta(t);
-               }
-               if (t->wait != 0) {
-                       t->wait--;
-               }
-       }
-}
-
-//void adlib_shut_up();
-void midi_reset_tracks();
-void midi_reset_channels();
-
-void midi_tick() {
-       if (midi_playing) {
-               unsigned int i;
-               int eof=0;
-
-               for (i=0;i < midi_trk_count;i++) {
-                       midi_tick_track(i);
-                       eof += midi_trk[i].eof?1:0;
-               }
-
-               if (eof >= midi_trk_count) {
-                       adlib_shut_up();
-                       midi_reset_tracks();
-                       midi_reset_channels();
-               }
-       }
-}
-
-/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */
-void interrupt irq0() {
-//     midi_tick();
-       irq0_ticks++;
-       if ((irq0_cnt += irq0_add) >= irq0_max) {
-               irq0_cnt -= irq0_max;
-               old_irq0();
-       }
-       else {
-               p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI);
-       }
-}
-
-void adlib_shut_up() {
-       int i;
-
-       memset(adlib_fm,0,sizeof(adlib_fm));
-       memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));
-       for (i=0;i < adlib_fm_voices;i++) {
-               struct adlib_fm_operator *f;
-               f = &adlib_fm[i].mod;
-               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
-               f = &adlib_fm[i].car;
-               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
-       }
-
-       for (i=0;i < adlib_fm_voices;i++) {
-               struct adlib_fm_operator *f;
-
-               midi_notes[i].busy = 0;
-               midi_notes[i].note_channel = 0;
-
-               f = &adlib_fm[i].mod;
-               f->mod_multiple = 1;
-               f->total_level = 63 - 16;
-               f->attack_rate = 15;
-               f->decay_rate = 4;
-               f->sustain_level = 0;
-               f->release_rate = 8;
-               f->f_number = 400;
-               f->sustain = 1;
-               f->octave = 4;
-               f->key_on = 0;
-
-               f = &adlib_fm[i].car;
-               f->mod_multiple = 1;
-               f->total_level = 63 - 16;
-               f->attack_rate = 15;
-               f->decay_rate = 4;
-               f->sustain_level = 0;
-               f->release_rate = 8;
-               f->f_number = 0;
-               f->sustain = 1;
-               f->octave = 0;
-               f->key_on = 0;
-       }
-
-       adlib_apply_all();
-}
-
-void midi_reset_track(unsigned int i) {
-       struct midi_track *t;
-
-       if (i >= MIDI_MAX_TRACKS) return;
-       t = &midi_trk[i];
-       t->eof = 0;
-       t->last_status = 0;
-       t->us_tick_cnt_mtpq = 0;
-       t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */
-       t->read = midi_trk[i].raw;
-       t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */
-}
-
-void midi_reset_tracks() {
-       int i;
-
-       for (i=0;i < midi_trk_count;i++)
-               midi_reset_track(i);
-}
-
-void midi_reset_channels() {
-       int i;
-
-       for (i=0;i < MIDI_MAX_CHANNELS;i++) {
-               midi_ch[i].program = 0;
-       }
-}
-
-int load_midi_file(const char *path) {
-       unsigned char tmp[256];
-       unsigned int tracks=0;
-       unsigned int tracki=0;
-       int fd;
-
-       fd = open(path,O_RDONLY|O_BINARY);
-       if (fd < 0) {
-               printf("Failed to load file %s\n",path);
-               return 0;
-       }
-
-       ticks_per_quarter_note = 0;
-       while (read(fd,tmp,8) == 8) {
-               uint32_t sz;
-
-               sz =    ((uint32_t)tmp[4] << (uint32_t)24) |
-                       ((uint32_t)tmp[5] << (uint32_t)16) |
-                       ((uint32_t)tmp[6] << (uint32_t)8) |
-                       ((uint32_t)tmp[7] << (uint32_t)0);
-               if (!memcmp(tmp,"MThd",4)) {
-                       unsigned short t,tdiv;
-
-                       if (sz < 6 || sz > 255) {
-                               fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz);
-                               goto err;
-                       }
-                       if (read(fd,tmp,(int)sz) != (int)sz) {
-                               fprintf(stderr,"MThd read error\n");
-                               goto err;
-                       }
-
-                       /* byte 0-1 = format type (0,1 or 2) */
-                       /* byte 2-3 = number of tracks */
-                       /* byte 4-5 = time divison */
-                       t = tmp[1] | (tmp[0] << 8);
-                       if (t > 1) {
-                               fprintf(stderr,"MThd type %u not supported\n",t);
-                               goto err; /* we only take type 0 or 1, don't support 2 */
-                       }
-                       tracks = tmp[3] | (tmp[2] << 8);
-                       if (tracks > MIDI_MAX_TRACKS) {
-                               fprintf(stderr,"MThd too many (%u) tracks\n",tracks);
-                               goto err;
-                       }
-                       tdiv = tmp[5] | (tmp[4] << 8);
-                       if (tdiv & 0x8000) {
-                               fprintf(stderr,"MThd SMPTE time division not supported\n");
-                               goto err; /* we do not support the SMPTE form */
-                       }
-                       if (tdiv == 0) {
-                               fprintf(stderr,"MThd time division == 0\n");
-                               goto err;
-                       }
-                       ticks_per_quarter_note = tdiv;
-               }
-               else if (!memcmp(tmp,"MTrk",4)) {
-                       if (sz == 0UL) continue;
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-                       if (sz > (640UL << 10UL)) goto err; /* 640KB */
-#elif TARGET_MSDOS == 32
-                       if (sz > (1UL << 20UL)) goto err; /* 1MB */
-#else
-                       if (sz > (60UL << 10UL)) goto err; /* 60KB */
-#endif
-                       if (tracki >= MIDI_MAX_TRACKS) goto err;
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-                       {
-                               unsigned segv;
-
-                               /* NTS: _fmalloc() is still limited to 64KB sizes */
-                               if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err;
-                               midi_trk[tracki].raw = MK_FP(segv,0);
-                       }
-#else
-                       midi_trk[tracki].raw = malloc(sz);
-#endif
-                       if (midi_trk[tracki].raw == NULL) goto err;
-                       midi_trk[tracki].read = midi_trk[tracki].raw;
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-                       {
-                               unsigned char far *p = midi_trk[tracki].raw;
-                               unsigned long rem = (unsigned long)sz;
-                               unsigned long cando;
-                               unsigned read;
-
-                               while (rem != 0UL) {
-                                       read = 0;
-
-                                       cando = 0x10000UL - (unsigned long)FP_OFF(p);
-                                       if (cando > rem) cando = rem;
-                                       if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */
-
-                                       if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err;
-                                       if (read != (unsigned)cando) goto err;
-
-                                       rem -= cando;
-                                       if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL)
-                                               p = MK_FP(FP_SEG(p)+0x1000,0);
-                                       else
-                                               p += (unsigned)cando;
-                               }
-
-                               cando = farptr2phys(p);
-                               midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF);
-                       }
-#else
-                       midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz;
-                       if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err;
-#endif
-                       tracki++;
-               }
-               else {
-                       fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]);
-                       goto err;
-               }
-       }
-       if (tracki == 0 || ticks_per_quarter_note == 0) goto err;
-       midi_trk_count = tracki;
-
-       fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note);
-
-       close(fd);
-       return 1;
-err:
-       close(fd);
-       return 0;
-}
+/* midi.c\r
+ *\r
+ * Adlib OPL2/OPL3 FM synthesizer chipset test program.\r
+ * Play MIDI file using the OPLx synthesizer (well, poorly anyway)\r
+ * (C) 2010-2012 Jonathan Campbell.\r
+ * Hackipedia DOS library.\r
+ *\r
+ * This code is licensed under the LGPL.\r
+ * <insert LGPL legal text here>\r
+ *\r
+ * Compiles for intended target environments:\r
+ *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]\r
+ */\r
+\r
+#include "src/lib/midi.h"\r
+\r
+static unsigned int            midi_trk_count=0;\r
+struct midi_note               midi_notes[ADLIB_FM_VOICES];\r
+struct midi_channel            midi_ch[MIDI_MAX_CHANNELS];\r
+struct midi_track              midi_trk[MIDI_MAX_TRACKS];\r
+\r
+/* MIDI params. Nobody ever said it was a straightforward standard!\r
+ * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */\r
+static unsigned int ticks_per_quarter_note=0;  /* "Ticks per beat" */\r
+\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */\r
+       return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p));\r
+}\r
+#endif\r
+\r
+static inline unsigned char midi_trk_read(struct midi_track *t) {\r
+       unsigned char c;\r
+\r
+       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */\r
+       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) {\r
+               t->eof = 1;\r
+               return 0xFF;\r
+       }\r
+\r
+       c = *(t->read);\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+       if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */\r
+               t->read = MK_FP(FP_SEG(t->read)+0x1,0);\r
+       else\r
+               t->read++;\r
+#else\r
+       t->read++;\r
+#endif\r
+       return c;\r
+}\r
+\r
+void midi_trk_end(struct midi_track *t) {\r
+       t->wait = ~0UL;\r
+       t->read = t->fence;\r
+}\r
+\r
+void midi_trk_skip(struct midi_track *t,unsigned long len) {\r
+       unsigned long rem;\r
+\r
+       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */\r
+       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence)\r
+               return;\r
+\r
+       if (len > 0xFFF0UL) {\r
+               midi_trk_end(t);\r
+               return;\r
+       }\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+       {\r
+               unsigned long tt;\r
+\r
+               tt = farptr2phys(t->read);\r
+               rem = farptr2phys(t->fence) - tt;\r
+               if (rem > len) rem = len;\r
+               tt += rem;\r
+               t->read = MK_FP(tt>>4,tt&0xF);\r
+       }\r
+#else\r
+       rem = (unsigned long)(t->fence - t->read);\r
+       if (len > rem) len = rem;\r
+       t->read += len;\r
+#endif\r
+}\r
+\r
+static const uint32_t midikeys_freqs[0x80] = {\r
+       0x00082d01,     /* key 0 = 8.17579891564371Hz */\r
+       0x0008a976,     /* key 1 = 8.66195721802725Hz */\r
+       0x00092d51,     /* key 2 = 9.17702399741899Hz */\r
+       0x0009b904,     /* key 3 = 9.72271824131503Hz */\r
+       0x000a4d05,     /* key 4 = 10.3008611535272Hz */\r
+       0x000ae9d3,     /* key 5 = 10.9133822322814Hz */\r
+       0x000b8ff4,     /* key 6 = 11.5623257097386Hz */\r
+       0x000c3ff6,     /* key 7 = 12.2498573744297Hz */\r
+       0x000cfa70,     /* key 8 = 12.9782717993733Hz */\r
+       0x000dc000,     /* key 9 = 13.75Hz */\r
+       0x000e914f,     /* key 10 = 14.5676175474403Hz */\r
+       0x000f6f11,     /* key 11 = 15.4338531642539Hz */\r
+       0x00105a02,     /* key 12 = 16.3515978312874Hz */\r
+       0x001152ec,     /* key 13 = 17.3239144360545Hz */\r
+       0x00125aa2,     /* key 14 = 18.354047994838Hz */\r
+       0x00137208,     /* key 15 = 19.4454364826301Hz */\r
+       0x00149a0a,     /* key 16 = 20.6017223070544Hz */\r
+       0x0015d3a6,     /* key 17 = 21.8267644645627Hz */\r
+       0x00171fe9,     /* key 18 = 23.1246514194771Hz */\r
+       0x00187fed,     /* key 19 = 24.4997147488593Hz */\r
+       0x0019f4e0,     /* key 20 = 25.9565435987466Hz */\r
+       0x001b8000,     /* key 21 = 27.5Hz */\r
+       0x001d229e,     /* key 22 = 29.1352350948806Hz */\r
+       0x001ede22,     /* key 23 = 30.8677063285078Hz */\r
+       0x0020b404,     /* key 24 = 32.7031956625748Hz */\r
+       0x0022a5d8,     /* key 25 = 34.647828872109Hz */\r
+       0x0024b545,     /* key 26 = 36.7080959896759Hz */\r
+       0x0026e410,     /* key 27 = 38.8908729652601Hz */\r
+       0x00293414,     /* key 28 = 41.2034446141087Hz */\r
+       0x002ba74d,     /* key 29 = 43.6535289291255Hz */\r
+       0x002e3fd2,     /* key 30 = 46.2493028389543Hz */\r
+       0x0030ffda,     /* key 31 = 48.9994294977187Hz */\r
+       0x0033e9c0,     /* key 32 = 51.9130871974931Hz */\r
+       0x00370000,     /* key 33 = 55Hz */\r
+       0x003a453d,     /* key 34 = 58.2704701897612Hz */\r
+       0x003dbc44,     /* key 35 = 61.7354126570155Hz */\r
+       0x00416809,     /* key 36 = 65.4063913251497Hz */\r
+       0x00454bb0,     /* key 37 = 69.295657744218Hz */\r
+       0x00496a8b,     /* key 38 = 73.4161919793519Hz */\r
+       0x004dc820,     /* key 39 = 77.7817459305202Hz */\r
+       0x00526829,     /* key 40 = 82.4068892282175Hz */\r
+       0x00574e9b,     /* key 41 = 87.307057858251Hz */\r
+       0x005c7fa4,     /* key 42 = 92.4986056779086Hz */\r
+       0x0061ffb5,     /* key 43 = 97.9988589954373Hz */\r
+       0x0067d380,     /* key 44 = 103.826174394986Hz */\r
+       0x006e0000,     /* key 45 = 110Hz */\r
+       0x00748a7b,     /* key 46 = 116.540940379522Hz */\r
+       0x007b7888,     /* key 47 = 123.470825314031Hz */\r
+       0x0082d012,     /* key 48 = 130.812782650299Hz */\r
+       0x008a9760,     /* key 49 = 138.591315488436Hz */\r
+       0x0092d517,     /* key 50 = 146.832383958704Hz */\r
+       0x009b9041,     /* key 51 = 155.56349186104Hz */\r
+       0x00a4d053,     /* key 52 = 164.813778456435Hz */\r
+       0x00ae9d36,     /* key 53 = 174.614115716502Hz */\r
+       0x00b8ff49,     /* key 54 = 184.997211355817Hz */\r
+       0x00c3ff6a,     /* key 55 = 195.997717990875Hz */\r
+       0x00cfa700,     /* key 56 = 207.652348789973Hz */\r
+       0x00dc0000,     /* key 57 = 220Hz */\r
+       0x00e914f6,     /* key 58 = 233.081880759045Hz */\r
+       0x00f6f110,     /* key 59 = 246.941650628062Hz */\r
+       0x0105a025,     /* key 60 = 261.625565300599Hz */\r
+       0x01152ec0,     /* key 61 = 277.182630976872Hz */\r
+       0x0125aa2e,     /* key 62 = 293.664767917408Hz */\r
+       0x01372082,     /* key 63 = 311.126983722081Hz */\r
+       0x0149a0a7,     /* key 64 = 329.62755691287Hz */\r
+       0x015d3a6d,     /* key 65 = 349.228231433004Hz */\r
+       0x0171fe92,     /* key 66 = 369.994422711634Hz */\r
+       0x0187fed4,     /* key 67 = 391.995435981749Hz */\r
+       0x019f4e00,     /* key 68 = 415.304697579945Hz */\r
+       0x01b80000,     /* key 69 = 440Hz */\r
+       0x01d229ec,     /* key 70 = 466.16376151809Hz */\r
+       0x01ede220,     /* key 71 = 493.883301256124Hz */\r
+       0x020b404a,     /* key 72 = 523.251130601197Hz */\r
+       0x022a5d81,     /* key 73 = 554.365261953744Hz */\r
+       0x024b545c,     /* key 74 = 587.329535834815Hz */\r
+       0x026e4104,     /* key 75 = 622.253967444162Hz */\r
+       0x0293414f,     /* key 76 = 659.25511382574Hz */\r
+       0x02ba74da,     /* key 77 = 698.456462866008Hz */\r
+       0x02e3fd24,     /* key 78 = 739.988845423269Hz */\r
+       0x030ffda9,     /* key 79 = 783.990871963499Hz */\r
+       0x033e9c01,     /* key 80 = 830.60939515989Hz */\r
+       0x03700000,     /* key 81 = 880Hz */\r
+       0x03a453d8,     /* key 82 = 932.32752303618Hz */\r
+       0x03dbc440,     /* key 83 = 987.766602512248Hz */\r
+       0x04168094,     /* key 84 = 1046.50226120239Hz */\r
+       0x0454bb03,     /* key 85 = 1108.73052390749Hz */\r
+       0x0496a8b8,     /* key 86 = 1174.65907166963Hz */\r
+       0x04dc8208,     /* key 87 = 1244.50793488832Hz */\r
+       0x0526829e,     /* key 88 = 1318.51022765148Hz */\r
+       0x0574e9b5,     /* key 89 = 1396.91292573202Hz */\r
+       0x05c7fa49,     /* key 90 = 1479.97769084654Hz */\r
+       0x061ffb53,     /* key 91 = 1567.981743927Hz */\r
+       0x067d3802,     /* key 92 = 1661.21879031978Hz */\r
+       0x06e00000,     /* key 93 = 1760Hz */\r
+       0x0748a7b1,     /* key 94 = 1864.65504607236Hz */\r
+       0x07b78880,     /* key 95 = 1975.5332050245Hz */\r
+       0x082d0128,     /* key 96 = 2093.00452240479Hz */\r
+       0x08a97607,     /* key 97 = 2217.46104781498Hz */\r
+       0x092d5171,     /* key 98 = 2349.31814333926Hz */\r
+       0x09b90410,     /* key 99 = 2489.01586977665Hz */\r
+       0x0a4d053c,     /* key 100 = 2637.02045530296Hz */\r
+       0x0ae9d36b,     /* key 101 = 2793.82585146403Hz */\r
+       0x0b8ff493,     /* key 102 = 2959.95538169308Hz */\r
+       0x0c3ff6a7,     /* key 103 = 3135.96348785399Hz */\r
+       0x0cfa7005,     /* key 104 = 3322.43758063956Hz */\r
+       0x0dc00000,     /* key 105 = 3520Hz */\r
+       0x0e914f62,     /* key 106 = 3729.31009214472Hz */\r
+       0x0f6f1100,     /* key 107 = 3951.06641004899Hz */\r
+       0x105a0250,     /* key 108 = 4186.00904480958Hz */\r
+       0x1152ec0e,     /* key 109 = 4434.92209562995Hz */\r
+       0x125aa2e3,     /* key 110 = 4698.63628667852Hz */\r
+       0x13720820,     /* key 111 = 4978.03173955329Hz */\r
+       0x149a0a79,     /* key 112 = 5274.04091060592Hz */\r
+       0x15d3a6d6,     /* key 113 = 5587.65170292806Hz */\r
+       0x171fe927,     /* key 114 = 5919.91076338615Hz */\r
+       0x187fed4e,     /* key 115 = 6271.92697570799Hz */\r
+       0x19f4e00a,     /* key 116 = 6644.87516127912Hz */\r
+       0x1b800000,     /* key 117 = 7040Hz */\r
+       0x1d229ec4,     /* key 118 = 7458.62018428944Hz */\r
+       0x1ede2200,     /* key 119 = 7902.13282009799Hz */\r
+       0x20b404a1,     /* key 120 = 8372.01808961916Hz */\r
+       0x22a5d81c,     /* key 121 = 8869.84419125991Hz */\r
+       0x24b545c7,     /* key 122 = 9397.27257335704Hz */\r
+       0x26e41040,     /* key 123 = 9956.06347910659Hz */\r
+       0x293414f2,     /* key 124 = 10548.0818212118Hz */\r
+       0x2ba74dac,     /* key 125 = 11175.3034058561Hz */\r
+       0x2e3fd24f,     /* key 126 = 11839.8215267723Hz */\r
+       0x30ffda9c      /* key 127 = 12543.853951416Hz */\r
+};\r
+\r
+static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) {\r
+       return midikeys_freqs[key&0x7F];\r
+}\r
+\r
+static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) {\r
+       unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */\r
+       unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */\r
+       unsigned int i,freen=~0;\r
+\r
+       for (i=0;i < ADLIB_FM_VOICES;i++) {\r
+               if (midi_notes[i].busy) {\r
+                       if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key)\r
+                               return &midi_notes[i];\r
+               }\r
+               else {\r
+                       if (freen == ~0) freen = i;\r
+               }\r
+       }\r
+\r
+       if (do_alloc && freen != ~0) return &midi_notes[freen];\r
+       return NULL;\r
+}\r
+\r
+static void drop_fm_note(struct midi_channel *ch,unsigned char key) {\r
+       unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */\r
+       unsigned int i;\r
+\r
+       for (i=0;i < ADLIB_FM_VOICES;i++) {\r
+               if (midi_notes[i].busy && midi_notes[i].note_channel == ach) {\r
+                       midi_notes[i].busy = 0;\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {\r
+       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0);\r
+       uint32_t freq = midi_note_freq(ch,key);\r
+       unsigned int ach;\r
+\r
+       if (note == NULL) return;\r
+\r
+       note->busy = 1;\r
+       note->note_number = key;\r
+       note->note_velocity = vel;\r
+       note->note_track = (unsigned int)(t - midi_trk);\r
+       note->note_channel = (unsigned int)(ch - midi_ch);\r
+       ach = (unsigned int)(note - midi_notes); /* which FM channel? */\r
+       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);\r
+       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */\r
+       adlib_fm[ach].mod.sustain_level = vel >> 3;\r
+       adlib_fm[ach].mod.key_on = 1;\r
+       adlib_update_groupA0(ach,&adlib_fm[ach]);\r
+}\r
+\r
+static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {\r
+       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1);\r
+       uint32_t freq = midi_note_freq(ch,key);\r
+       unsigned int ach;\r
+\r
+       /* HACK: Ignore percussion */\r
+       if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ ||\r
+               (ch->program >= 112 && ch->program <= 119)/*Percussive*/ ||\r
+               ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/)\r
+               return;\r
+\r
+       if (note == NULL) {\r
+               /* then we'll have to knock one off to make room */\r
+               drop_fm_note(ch,key);\r
+               note = get_fm_note(t,ch,key,1);\r
+               if (note == NULL) return;\r
+       }\r
+\r
+       note->busy = 1;\r
+       note->note_number = key;\r
+       note->note_velocity = vel;\r
+       note->note_track = (unsigned int)(t - midi_trk);\r
+       note->note_channel = (unsigned int)(ch - midi_ch);\r
+       ach = (unsigned int)(note - midi_notes); /* which FM channel? */\r
+       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);\r
+       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */\r
+       adlib_fm[ach].mod.sustain_level = vel >> 3;\r
+       adlib_fm[ach].mod.key_on = 1;\r
+       adlib_update_groupA0(ach,&adlib_fm[ach]);\r
+}\r
+\r
+static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {\r
+       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0);\r
+       uint32_t freq = midi_note_freq(ch,key);\r
+       unsigned int ach;\r
+\r
+       if (note == NULL) return;\r
+\r
+       note->busy = 0;\r
+       ach = (unsigned int)(note - midi_notes); /* which FM channel? */\r
+       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);\r
+       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */\r
+       adlib_fm[ach].mod.sustain_level = vel >> 3;\r
+       adlib_fm[ach].mod.key_on = 0;\r
+       adlib_update_groupA0(ach,&adlib_fm[ach]);\r
+}\r
+\r
+static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) {\r
+}\r
+\r
+static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) {\r
+       ch->program = inst;\r
+}\r
+\r
+static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) {\r
+}\r
+\r
+static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) {\r
+}\r
+\r
+unsigned long midi_trk_read_delta(struct midi_track *t) {\r
+       unsigned long tc = 0;\r
+       unsigned char c = 0,b;\r
+\r
+       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */\r
+       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence)\r
+               return tc;\r
+\r
+       while (c < 4) {\r
+               b = midi_trk_read(t);\r
+               tc = (tc << 7UL) + (unsigned long)(b&0x7F);\r
+               if (!(b&0x80)) break;\r
+               c++;\r
+       }\r
+\r
+       return tc;\r
+}\r
+\r
+void midi_tick_track(unsigned int i) {\r
+       struct midi_track *t = midi_trk + i;\r
+       struct midi_channel *ch;\r
+       unsigned char b,c,d;\r
+       int cnt=0;\r
+\r
+       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */\r
+       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) {\r
+               t->eof = 1;\r
+               return;\r
+       }\r
+\r
+       t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note;\r
+       while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) {\r
+               t->us_tick_cnt_mtpq -= t->us_per_quarter_note;\r
+               cnt++;\r
+\r
+               while (t->wait == 0) {\r
+                       if ((unsigned long)t->read >= (unsigned long)t->fence) {\r
+                               t->eof = 1;\r
+                               break;\r
+                       }\r
+\r
+                       /* read pointer should be pointing at MIDI event bytes, just after the time delay */\r
+                       b = midi_trk_read(t);\r
+                       if (b&0x80) {\r
+                               if (b < 0xF8) {\r
+                                       if (b >= 0xF0)\r
+                                               t->last_status = 0;\r
+                                       else\r
+                                               t->last_status = b;\r
+                               }\r
+                               if (b != 0x00 && ((b&0xF8) != 0xF0))\r
+                                       c = midi_trk_read(t);\r
+                       }\r
+                       else {\r
+                               /* blegh. last status */\r
+                               c = b;\r
+                               b = t->last_status;\r
+                       }\r
+                       switch (b>>4) {\r
+                               case 0x8: { /* note off */\r
+                                       d = midi_trk_read(t);\r
+                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */\r
+                                       on_key_off(t,ch,c,d);\r
+                                       } break;\r
+                               case 0x9: { /* note on */\r
+                                       d = midi_trk_read(t);\r
+                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */\r
+                                       if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */\r
+                                       else on_key_off(t,ch,c,d);\r
+                                       } break;\r
+                               case 0xA: { /* polyphonic aftertouch */\r
+                                       d = midi_trk_read(t);\r
+                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */\r
+                                       on_key_aftertouch(t,ch,c,d);\r
+                                       } break;\r
+                               case 0xB: { /* control change */\r
+                                       d = midi_trk_read(t);\r
+                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */\r
+                                       on_control_change(t,ch,c,d);\r
+                                       } break;\r
+                               case 0xC: { /* program change */\r
+                                       on_program_change(t,ch,c); /* c=instrument d=not used */\r
+                                       } break;\r
+                               case 0xD: { /* channel aftertouch */\r
+                                       on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */\r
+                                       } break;\r
+                               case 0xE: { /* pitch bend */\r
+                                       d = midi_trk_read(t);\r
+                                       on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */\r
+                                       } break;\r
+                               case 0xF: { /* event */\r
+                                       if (b == 0xFF) {\r
+                                               if (c == 0x7F) { /* c=type d=len */\r
+                                                       unsigned long len = midi_trk_read_delta(t);\r
+//====\r
+                                                       fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence);\r
+//====\r
+                                                       if (len < 512UL) {\r
+                                                               /* unknown */\r
+                                                               midi_trk_skip(t,len);\r
+                                                       }\r
+                                                       else {\r
+                                                               midi_trk_end(t);\r
+                                                       }\r
+                                               }\r
+                                               else if (c < 0x7F) {\r
+                                                       d = midi_trk_read(t);\r
+\r
+                                                       if (c == 0x51 && d >= 3) {\r
+                                                               d -= 3;\r
+                                                               t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+\r
+                                                                       ((unsigned long)midi_trk_read(t)<<8UL)+\r
+                                                                       ((unsigned long)midi_trk_read(t)<<0UL);\r
+\r
+                                                               if (1/*TODO: If format 0 or format 1*/) {\r
+                                                                       /* Ugh. Unless format 2, the tempo applies to all tracks */\r
+                                                                       int j;\r
+\r
+                                                                       for (j=0;j < midi_trk_count;j++) {\r
+                                                                               if (j != i) midi_trk[j].us_per_quarter_note =\r
+                                                                                       t->us_per_quarter_note;\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+                                                       else {\r
+//====\r
+                                                               fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence);\r
+//====\r
+                                                       }\r
+\r
+                                                       midi_trk_skip(t,d);\r
+                                               }\r
+                                               else {\r
+                                                       fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence);\r
+                                               }\r
+                                       }\r
+                                       else {\r
+                                               unsigned long len = midi_trk_read_delta(t);\r
+//====\r
+                                               fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence);\r
+//====\r
+                                               midi_trk_skip(t,len);\r
+                                       }\r
+                                       } break;\r
+                               default:\r
+                                       if (b != 0x00) {\r
+                                               fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence);\r
+                                               midi_trk_end(t);\r
+                                       }\r
+                                       break;\r
+                       };\r
+\r
+                       /* and then read the next event */\r
+                       t->wait = midi_trk_read_delta(t);\r
+               }\r
+               if (t->wait != 0) {\r
+                       t->wait--;\r
+               }\r
+       }\r
+}\r
+\r
+//void adlib_shut_up();\r
+void midi_reset_tracks();\r
+void midi_reset_channels();\r
+\r
+void midi_tick() {\r
+       if (midi_playing) {\r
+               unsigned int i;\r
+               int eof=0;\r
+\r
+               for (i=0;i < midi_trk_count;i++) {\r
+                       midi_tick_track(i);\r
+                       eof += midi_trk[i].eof?1:0;\r
+               }\r
+\r
+               if (eof >= midi_trk_count) {\r
+                       adlib_shut_up();\r
+                       midi_reset_tracks();\r
+                       midi_reset_channels();\r
+               }\r
+       }\r
+}\r
+\r
+/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */\r
+void interrupt irq0() {\r
+//     midi_tick();\r
+       irq0_ticks++;\r
+       if ((irq0_cnt += irq0_add) >= irq0_max) {\r
+               irq0_cnt -= irq0_max;\r
+               old_irq0();\r
+       }\r
+       else {\r
+               p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI);\r
+       }\r
+}\r
+\r
+void adlib_shut_up() {\r
+       int i;\r
+\r
+       memset(adlib_fm,0,sizeof(adlib_fm));\r
+       memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));\r
+       for (i=0;i < adlib_fm_voices;i++) {\r
+               struct adlib_fm_operator *f;\r
+               f = &adlib_fm[i].mod;\r
+               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\r
+               f = &adlib_fm[i].car;\r
+               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\r
+       }\r
+\r
+       for (i=0;i < adlib_fm_voices;i++) {\r
+               struct adlib_fm_operator *f;\r
+\r
+               midi_notes[i].busy = 0;\r
+               midi_notes[i].note_channel = 0;\r
+\r
+               f = &adlib_fm[i].mod;\r
+               f->mod_multiple = 1;\r
+               f->total_level = 63 - 16;\r
+               f->attack_rate = 15;\r
+               f->decay_rate = 4;\r
+               f->sustain_level = 0;\r
+               f->release_rate = 8;\r
+               f->f_number = 400;\r
+               f->sustain = 1;\r
+               f->octave = 4;\r
+               f->key_on = 0;\r
+\r
+               f = &adlib_fm[i].car;\r
+               f->mod_multiple = 1;\r
+               f->total_level = 63 - 16;\r
+               f->attack_rate = 15;\r
+               f->decay_rate = 4;\r
+               f->sustain_level = 0;\r
+               f->release_rate = 8;\r
+               f->f_number = 0;\r
+               f->sustain = 1;\r
+               f->octave = 0;\r
+               f->key_on = 0;\r
+       }\r
+\r
+       adlib_apply_all();\r
+}\r
+\r
+void midi_reset_track(unsigned int i) {\r
+       struct midi_track *t;\r
+\r
+       if (i >= MIDI_MAX_TRACKS) return;\r
+       t = &midi_trk[i];\r
+       t->eof = 0;\r
+       t->last_status = 0;\r
+       t->us_tick_cnt_mtpq = 0;\r
+       t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */\r
+       t->read = midi_trk[i].raw;\r
+       t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */\r
+}\r
+\r
+void midi_reset_tracks() {\r
+       int i;\r
+\r
+       for (i=0;i < midi_trk_count;i++)\r
+               midi_reset_track(i);\r
+}\r
+\r
+void midi_reset_channels() {\r
+       int i;\r
+\r
+       for (i=0;i < MIDI_MAX_CHANNELS;i++) {\r
+               midi_ch[i].program = 0;\r
+       }\r
+}\r
+\r
+int load_midi_file(const char *path) {\r
+       unsigned char tmp[256];\r
+       unsigned int tracks=0;\r
+       unsigned int tracki=0;\r
+       int fd;\r
+\r
+       fd = open(path,O_RDONLY|O_BINARY);\r
+       if (fd < 0) {\r
+               printf("Failed to load file %s\n",path);\r
+               return 0;\r
+       }\r
+\r
+       ticks_per_quarter_note = 0;\r
+       while (read(fd,tmp,8) == 8) {\r
+               uint32_t sz;\r
+\r
+               sz =    ((uint32_t)tmp[4] << (uint32_t)24) |\r
+                       ((uint32_t)tmp[5] << (uint32_t)16) |\r
+                       ((uint32_t)tmp[6] << (uint32_t)8) |\r
+                       ((uint32_t)tmp[7] << (uint32_t)0);\r
+               if (!memcmp(tmp,"MThd",4)) {\r
+                       unsigned short t,tdiv;\r
+\r
+                       if (sz < 6 || sz > 255) {\r
+                               fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz);\r
+                               goto err;\r
+                       }\r
+                       if (read(fd,tmp,(int)sz) != (int)sz) {\r
+                               fprintf(stderr,"MThd read error\n");\r
+                               goto err;\r
+                       }\r
+\r
+                       /* byte 0-1 = format type (0,1 or 2) */\r
+                       /* byte 2-3 = number of tracks */\r
+                       /* byte 4-5 = time divison */\r
+                       t = tmp[1] | (tmp[0] << 8);\r
+                       if (t > 1) {\r
+                               fprintf(stderr,"MThd type %u not supported\n",t);\r
+                               goto err; /* we only take type 0 or 1, don't support 2 */\r
+                       }\r
+                       tracks = tmp[3] | (tmp[2] << 8);\r
+                       if (tracks > MIDI_MAX_TRACKS) {\r
+                               fprintf(stderr,"MThd too many (%u) tracks\n",tracks);\r
+                               goto err;\r
+                       }\r
+                       tdiv = tmp[5] | (tmp[4] << 8);\r
+                       if (tdiv & 0x8000) {\r
+                               fprintf(stderr,"MThd SMPTE time division not supported\n");\r
+                               goto err; /* we do not support the SMPTE form */\r
+                       }\r
+                       if (tdiv == 0) {\r
+                               fprintf(stderr,"MThd time division == 0\n");\r
+                               goto err;\r
+                       }\r
+                       ticks_per_quarter_note = tdiv;\r
+               }\r
+               else if (!memcmp(tmp,"MTrk",4)) {\r
+                       if (sz == 0UL) continue;\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+                       if (sz > (640UL << 10UL)) goto err; /* 640KB */\r
+#elif TARGET_MSDOS == 32\r
+                       if (sz > (1UL << 20UL)) goto err; /* 1MB */\r
+#else\r
+                       if (sz > (60UL << 10UL)) goto err; /* 60KB */\r
+#endif\r
+                       if (tracki >= MIDI_MAX_TRACKS) goto err;\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+                       {\r
+                               unsigned segv;\r
+\r
+                               /* NTS: _fmalloc() is still limited to 64KB sizes */\r
+                               if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err;\r
+                               midi_trk[tracki].raw = MK_FP(segv,0);\r
+                       }\r
+#else\r
+                       midi_trk[tracki].raw = malloc(sz);\r
+#endif\r
+                       if (midi_trk[tracki].raw == NULL) goto err;\r
+                       midi_trk[tracki].read = midi_trk[tracki].raw;\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+                       {\r
+                               unsigned char far *p = midi_trk[tracki].raw;\r
+                               unsigned long rem = (unsigned long)sz;\r
+                               unsigned long cando;\r
+                               unsigned read;\r
+\r
+                               while (rem != 0UL) {\r
+                                       read = 0;\r
+\r
+                                       cando = 0x10000UL - (unsigned long)FP_OFF(p);\r
+                                       if (cando > rem) cando = rem;\r
+                                       if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */\r
+\r
+                                       if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err;\r
+                                       if (read != (unsigned)cando) goto err;\r
+\r
+                                       rem -= cando;\r
+                                       if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL)\r
+                                               p = MK_FP(FP_SEG(p)+0x1000,0);\r
+                                       else\r
+                                               p += (unsigned)cando;\r
+                               }\r
+\r
+                               cando = farptr2phys(p);\r
+                               midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF);\r
+                       }\r
+#else\r
+                       midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz;\r
+                       if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err;\r
+#endif\r
+                       tracki++;\r
+               }\r
+               else {\r
+                       fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]);\r
+                       goto err;\r
+               }\r
+       }\r
+       if (tracki == 0 || ticks_per_quarter_note == 0) goto err;\r
+       midi_trk_count = tracki;\r
+\r
+       fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note);\r
+\r
+       close(fd);\r
+       return 1;\r
+err:\r
+       close(fd);\r
+       return 0;\r
+}\r
index ac740c809d5ce036a09a24bf994adc19a0232add..356255d24c992ab1001af18c86458e21dda9cd41 100755 (executable)
@@ -1,83 +1,83 @@
-/* midi.h
- *
- * Adlib OPL2/OPL3 FM synthesizer chipset test program.
- * Play MIDI file using the OPLx synthesizer (well, poorly anyway)
- * (C) 2010-2012 Jonathan Campbell.
- * Hackipedia DOS library.
- *
- * This code is licensed under the LGPL.
- * <insert LGPL legal text here>
- *
- * Compiles for intended target environments:
- *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]
- */
-
+/* midi.h\r
+ *\r
+ * Adlib OPL2/OPL3 FM synthesizer chipset test program.\r
+ * Play MIDI file using the OPLx synthesizer (well, poorly anyway)\r
+ * (C) 2010-2012 Jonathan Campbell.\r
+ * Hackipedia DOS library.\r
+ *\r
+ * This code is licensed under the LGPL.\r
+ * <insert LGPL legal text here>\r
+ *\r
+ * Compiles for intended target environments:\r
+ *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]\r
+ */\r
+\r
 #ifndef        __MIDI__\r
-#define        __MIDI__
-
-#include <stdio.h>
-#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <math.h>
-#include <dos.h>
-
-//#include "src/lib/doslib/vga.h"
-#include "src/lib/doslib/dos.h"
-#include "src/lib/16_head.h"
-#include "src/lib/doslib/8254.h"               /* 8254 timer */
-#include "src/lib/doslib/8259.h"
-//#include "src/lib/doslib/vgagui.h"
-//#include "src/lib/doslib/vgatty.h"
-#include "src/lib/doslib/adlib.h"
-
-/* one per OPL channel */
-struct midi_note {
-       unsigned char           note_number;
-       unsigned char           note_velocity;
-       unsigned char           note_track;     /* from what MIDI track */
-       unsigned char           note_channel;   /* from what MIDI channel */
-       unsigned int            busy:1;         /* if occupied */
-};
-
-struct midi_channel {
-       unsigned char           program;
-};
-
-struct midi_track {
-       /* track data, raw */
-       unsigned char*          raw;            /* raw data base */
-       unsigned char*          fence;          /* raw data end (last byte + 1) */
-       unsigned char*          read;           /* raw data read ptr */
-       /* state */
-       unsigned long           us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */
-       unsigned long           us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */
-       unsigned long           wait;
-       unsigned char           last_status;    /* MIDI last status byte */
-       unsigned int            eof:1;          /* we hit the end of the track */
-};
-
-#define MIDI_MAX_CHANNELS      16
-#define MIDI_MAX_TRACKS                64
-
-extern struct midi_note                midi_notes[ADLIB_FM_VOICES];
-extern struct midi_channel             midi_ch[MIDI_MAX_CHANNELS];
-extern struct midi_track               midi_trk[MIDI_MAX_TRACKS];
-
-static void (interrupt *old_irq0)();
-static volatile unsigned long irq0_ticks=0;
-static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0;
-static volatile unsigned char  midi_playing=0;
-
-int load_midi_file(const char *path);
-void interrupt irq0();
-void adlib_shut_up();
-void midi_reset_tracks();
-void midi_reset_channels();
-void midi_tick();
-
-#endif /* __MIDI__ */
+#define        __MIDI__\r
+\r
+#include <stdio.h>\r
+#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <malloc.h>\r
+#include <ctype.h>\r
+#include <fcntl.h>\r
+#include <math.h>\r
+#include <dos.h>\r
+\r
+//#include "src/lib/doslib/vga.h"\r
+#include "src/lib/doslib/dos.h"\r
+#include "src/lib/16_head.h"\r
+#include "src/lib/doslib/8254.h"               /* 8254 timer */\r
+#include "src/lib/doslib/8259.h"\r
+//#include "src/lib/doslib/vgagui.h"\r
+//#include "src/lib/doslib/vgatty.h"\r
+#include "src/lib/doslib/adlib.h"\r
+\r
+/* one per OPL channel */\r
+struct midi_note {\r
+       unsigned char           note_number;\r
+       unsigned char           note_velocity;\r
+       unsigned char           note_track;     /* from what MIDI track */\r
+       unsigned char           note_channel;   /* from what MIDI channel */\r
+       unsigned int            busy:1;         /* if occupied */\r
+};\r
+\r
+struct midi_channel {\r
+       unsigned char           program;\r
+};\r
+\r
+struct midi_track {\r
+       /* track data, raw */\r
+       unsigned char*          raw;            /* raw data base */\r
+       unsigned char*          fence;          /* raw data end (last byte + 1) */\r
+       unsigned char*          read;           /* raw data read ptr */\r
+       /* state */\r
+       unsigned long           us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */\r
+       unsigned long           us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */\r
+       unsigned long           wait;\r
+       unsigned char           last_status;    /* MIDI last status byte */\r
+       unsigned int            eof:1;          /* we hit the end of the track */\r
+};\r
+\r
+#define MIDI_MAX_CHANNELS      16\r
+#define MIDI_MAX_TRACKS                64\r
+\r
+extern struct midi_note                midi_notes[ADLIB_FM_VOICES];\r
+extern struct midi_channel             midi_ch[MIDI_MAX_CHANNELS];\r
+extern struct midi_track               midi_trk[MIDI_MAX_TRACKS];\r
+\r
+static void (interrupt *old_irq0)();\r
+static volatile unsigned long irq0_ticks=0;\r
+static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0;\r
+static volatile unsigned char  midi_playing=0;\r
+\r
+int load_midi_file(const char *path);\r
+void interrupt irq0();\r
+void adlib_shut_up();\r
+void midi_reset_tracks();\r
+void midi_reset_channels();\r
+void midi_tick();\r
+\r
+#endif /* __MIDI__ */\r
index 23202f2d50508828ebd4243f91a5b7b3096c59c6..3467a77dd3487169751b90b5ad516b025c6d8b26 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/*
- * Functions for handling modex and doing other basic graphics stuff.
- */
-#ifndef MODEX16_H
-#define MODEX16_H
-
-#include "src/lib/16_head.h"
-#include "src/lib/bitmap.h"
-//#include "src/lib/planar.h"
-//#include "src/lib/modex16/16planar.h"
-#include "src/lib/16text.h"
-#include "src/lib/16render.h"
-////#include "src/lib/modex16/320x240.h"
-// #include "src/lib/modex16/320x200.h"
-// #include "src/lib/modex16/256x192.h"
-// #include "src/lib/modex16/192x144_.h"
-// #include "src/lib/modex16/160x120.h"
-
-#ifdef __WATCOMC__
-#include <hw/cpu/cpu.h>
-#include <hw/dos/dos.h>
-#include <hw/vga/vga.h>
-#include <hw/vga/vrl.h>
-#include <hw/vga/vrs.h>
-#endif
-
-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];
-} head;
-
-//320x240 = 20x15
-//192x144 = 12x9
-
-//temp defines
-#define TILEWH 16
-#define TILEWHD        TILEWH*2
-#define QUADWH                 TILEWH/2
-
-/* -========================== 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)
-#define     PALSIZE            768
-
-typedef union
-{
-       byte red;
-       byte green;
-       byte blue;
-} rgb_t;
-
-/* -======================= 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 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  defined in 16_head
-#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)
-
-/* -============================ Functions =============================- */
-/* mode switching, page, and plane functions */
-void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv);
-void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv);
-byte vgaGetMode();
-void modexLeave();
-void modexsetBaseXMode();
-page_t modexDefaultPage(page_t *p);
-page_t modexNextPage(page_t *p);
-page_t modexNextPageFlexibleSize(page_t *p, word x, word y);
-void modexCalcVmemRemain(video_t *video);
-void modexHiganbanaPageSetup(video_t *video);
-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);
-/* moved to src/lib/modex16/16render.c */
-void modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height);
-
-/* 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(bitmap_t *bmp, word *i, word qp, word aqoffset);
-void modexPalUpdate1(byte *p);
-void modexPalUpdate0(byte *p);
-void modexPalOverscan(word col);
-void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/);
-void modexputPixel(page_t *page, int x, int y, byte color);
-byte modexgetPixel(page_t *page, int x, int y);
-
-#if 0 // not needed anymore. maybe good for reference purposes though.
-static inline void modexwritepixel(page_t *page, int x, int y, word addr, byte color)
-{
-       /* Each address accesses four neighboring pixels, so set
-          Write Plane Enable according to which pixel we want
-          to modify.  The plane is determined by the two least
-          significant bits of the x-coordinate: */
-       modexSelectPlane(PLANE(x));
-       //outp(SC_INDEX, 0x02);
-       //outp(SC_DATA, 0x01 << (x & 3));
-
-       /* The offset of the pixel into the video segment is
-          offset = (width * y + x) / 4, and write the given
-          color to the plane we selected above.  Heed the active
-          page start selection. */
-       vga_state.vga_graphics_ram[addr] = color;
-}
-static inline byte modexreadPixel(page_t *page, int x, int y, word addr)
-{
-       /* Select the plane from which we must read the pixel color: */
-       outpw(GC_INDEX, 0x04);
-       outpw(GC_INDEX+1, x & 3);
-       return vga_state.vga_graphics_ram[addr];
-}
-#endif
-
-void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str);
-void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str);
-void modexpdump(page_t *pee);
-void modexcls(page_t *page, byte color, byte *Where);
-void modexWaitBorder();
-void modexprintmeminfo(video_t *v);
-
-#endif
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+/*\r
+ * Functions for handling modex and doing other basic graphics stuff.\r
+ */\r
+#ifndef MODEX16_H\r
+#define MODEX16_H\r
+\r
+#include "src/lib/16_head.h"\r
+#include "src/lib/bitmap.h"\r
+//#include "src/lib/planar.h"\r
+//#include "src/lib/modex16/16planar.h"\r
+#include "src/lib/16text.h"\r
+#include "src/lib/16render.h"\r
+////#include "src/lib/modex16/320x240.h"\r
+// #include "src/lib/modex16/320x200.h"\r
+// #include "src/lib/modex16/256x192.h"\r
+// #include "src/lib/modex16/192x144_.h"\r
+// #include "src/lib/modex16/160x120.h"\r
+\r
+#ifdef __WATCOMC__\r
+#include <hw/cpu/cpu.h>\r
+#include <hw/dos/dos.h>\r
+#include <hw/vga/vga.h>\r
+#include <hw/vga/vrl.h>\r
+#include <hw/vga/vrs.h>\r
+#endif\r
+\r
+static struct pcxHeader {\r
+       byte id;\r
+       byte version;\r
+       byte encoding;\r
+       byte bpp;\r
+       word xmin;\r
+       word ymin;\r
+       word xmax;\r
+       word ymax;\r
+       word hres;\r
+       word vres;\r
+       byte pal16[48];\r
+       byte res1;\r
+       word bpplane;\r
+       word palType;\r
+       word hScreenSize;\r
+       word vScreenSize;\r
+       byte padding[54];\r
+} head;\r
+\r
+//320x240 = 20x15\r
+//192x144 = 12x9\r
+\r
+//temp defines\r
+#define TILEWH 16\r
+#define TILEWHD        TILEWH*2\r
+#define QUADWH                 TILEWH/2\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
+#define     PALSIZE            768\r
+\r
+typedef union\r
+{\r
+       byte red;\r
+       byte green;\r
+       byte blue;\r
+} rgb_t;\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
+\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  defined in 16_head\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
+\r
+/* -============================ Functions =============================- */\r
+/* mode switching, page, and plane functions */\r
+void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv);\r
+void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv);\r
+byte vgaGetMode();\r
+void modexLeave();\r
+void modexsetBaseXMode();\r
+page_t modexDefaultPage(page_t *p);\r
+page_t modexNextPage(page_t *p);\r
+page_t modexNextPageFlexibleSize(page_t *p, word x, word y);\r
+void modexCalcVmemRemain(video_t *video);\r
+void modexHiganbanaPageSetup(video_t *video);\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
+/* moved to src/lib/modex16/16render.c */\r
+void modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height);\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(bitmap_t *bmp, word *i, word qp, word aqoffset);\r
+void modexPalUpdate1(byte *p);\r
+void modexPalUpdate0(byte *p);\r
+void modexPalOverscan(word col);\r
+void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/);\r
+void modexputPixel(page_t *page, int x, int y, byte color);\r
+byte modexgetPixel(page_t *page, int x, int y);\r
+\r
+#if 0 // not needed anymore. maybe good for reference purposes though.\r
+static inline void modexwritepixel(page_t *page, int x, int y, word addr, byte color)\r
+{\r
+       /* Each address accesses four neighboring pixels, so set\r
+          Write Plane Enable according to which pixel we want\r
+          to modify.  The plane is determined by the two least\r
+          significant bits of the x-coordinate: */\r
+       modexSelectPlane(PLANE(x));\r
+       //outp(SC_INDEX, 0x02);\r
+       //outp(SC_DATA, 0x01 << (x & 3));\r
+\r
+       /* The offset of the pixel into the video segment is\r
+          offset = (width * y + x) / 4, and write the given\r
+          color to the plane we selected above.  Heed the active\r
+          page start selection. */\r
+       vga_state.vga_graphics_ram[addr] = color;\r
+}\r
+static inline byte modexreadPixel(page_t *page, int x, int y, word addr)\r
+{\r
+       /* Select the plane from which we must read the pixel color: */\r
+       outpw(GC_INDEX, 0x04);\r
+       outpw(GC_INDEX+1, x & 3);\r
+       return vga_state.vga_graphics_ram[addr];\r
+}\r
+#endif\r
+\r
+void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str);\r
+void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str);\r
+void modexpdump(page_t *pee);\r
+void modexcls(page_t *page, byte color, byte *Where);\r
+void modexWaitBorder();\r
+void modexprintmeminfo(video_t *v);\r
+\r
+#endif\r
index eca613a8ccfbc1bdf60f5a4a0b837813c3dc3953..b94e768a77c1a8d4813111caa3e2bdae39c36cf3 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/*
-       scroll16 library~
-*/
-#include "src/lib/scroll16.h"
-
-void walk(map_view_t *pip, player_t *player, word pn)
-{
-       #define INC_PER_FRAME if(player[pn].q&1) player[pn].persist_aniframe++; if(player[pn].persist_aniframe>4) player[pn].persist_aniframe = 1;
-       //printf("player[%d].d=%d\n", pn, player[pn].d);
-       switch(player[pn].d)
-       {
-               //no direction
-               case 2:
-                       //0000pip[0].video->startclk = (*clockw);
-               break;
-               //right movement
-               case 3:
-                       //printf("pip[0].page->tilesw=%d        ", pip[0].page->tilesw); printf("pip[0].page->tw=%d\n", pip[0].page->tw);
-                       if(pip[0].tx >= 0 && pip[0].tx+pip[0].page->tw < pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx &&
-                       !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY))      //collision detection!
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       animatePlayer(pip, player, pn, 1);
-                                       ScrollRight(pip, player, 3, pn);
-                                       ScrollRight(pip, player, 2, pn);
-                                       mapScrollRight(pip, player, !(pip[0].video->p), pn);
-                                       mapScrollRight(pip, player, (pip[0].video->p), pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; }
-                       }
-                       else if(player[pn].tx < pip[0].map->width && !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY))
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       player[pn].x+=(player[pn].speed);
-                                       animatePlayer(pip, player, pn, 0);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; }
-                       }
-                       else
-                       {
-                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32);
-#ifdef SPRITE
-                               PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 24, 32, PLAYERBMPDATA);
-#else
-                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 14);
-#endif
-                               if(!pageflipflop) modexShowPage(pip[1].page);
-                               player[pn].d = 2;
-                       }
-                       player[pn].triggerx = player[pn].tx+1;
-                       player[pn].triggery = player[pn].ty;
-               break;
-
-               //left movement
-               case 1:
-                       if(pip[0].tx > 0 && pip[0].tx+pip[0].page->tw <= pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx &&
-                       !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY))    //collision detection!
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       animatePlayer(pip, player, pn, 1);
-                                       ScrollLeft(pip, player, 3, pn);
-                                       ScrollLeft(pip, player, 2, pn);
-                                       mapScrollLeft(pip, player, !(pip[0].video->p), pn);
-                                       mapScrollLeft(pip, player, (pip[0].video->p), pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; }
-                       }
-                       else if(player[pn].tx > 1 && !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY))
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       player[pn].x-=(player[pn].speed);
-                                       animatePlayer(pip, player, pn, 0);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; }
-                       }
-                       else
-                       {
-                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32);
-#ifdef SPRITE
-                               PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 96, 24, 32, PLAYERBMPDATA);
-#else
-                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 10);
-#endif
-                               if(!pageflipflop) modexShowPage(pip[1].page);
-                               player[pn].d = 2;
-                       }
-                       player[pn].triggerx = player[pn].tx-1;
-                       player[pn].triggery = player[pn].ty;
-               break;
-
-               //down movement
-               case 4:
-                       if(pip[0].ty >= 0 && pip[0].ty+pip[0].page->th < pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny &&
-                       !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY))      //collision detection!
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       animatePlayer(pip, player, pn, 1);
-                                       ScrollDown(pip, player, 3, pn);
-                                       ScrollDown(pip, player, 2, pn);
-                                       mapScrollDown(pip, player, !(pip[0].video->p), pn);
-                                       mapScrollDown(pip, player, (pip[0].video->p), pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; }
-                       }
-                       else if(player[pn].ty < pip[0].map->height && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY))
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       player[pn].y+=(player[pn].speed);
-                                       animatePlayer(pip, player, pn, 0);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; }
-                       }
-                       else
-                       {
-                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32);
-#ifdef SPRITE
-                               PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 64, 24, 32, PLAYERBMPDATA);
-#else
-                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 9);
-#endif
-                               if(!pageflipflop) modexShowPage(pip[1].page);
-                               player[pn].d = 2;
-                       }
-                       player[pn].triggerx = player[pn].tx;
-                       player[pn].triggery = player[pn].ty+1;
-               break;
-
-               //up movement
-               case 0:
-                       if(pip[0].ty > 0 && pip[0].ty+pip[0].page->th <= pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny &&
-                       !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY))    //collision detection!
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       animatePlayer(pip, player, pn, 1);
-                                       ScrollUp(pip, player, 3, pn);
-                                       ScrollUp(pip, player, 2, pn);
-                                       mapScrollUp(pip, player, !(pip[0].video->p), pn);
-                                       mapScrollUp(pip, player, (pip[0].video->p), pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; }
-                       }
-                       else if(player[pn].ty > 1 && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX &&  player[pn].ty-1 == TRIGGY))
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       INC_PER_FRAME;
-                                       player[pn].y-=(player[pn].speed);
-                                       animatePlayer(pip, player, 0, pn);
-                                       if(!pageflipflop) modexShowPage(pip[1].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; }
-                       }
-                       else
-                       {
-                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32);
-#ifdef SPRITE
-                               PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 0, 24, 32, PLAYERBMPDATA);
-#else
-                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 12);
-#endif
-                               if(!pageflipflop) modexShowPage(pip[1].page);
-                               player[pn].d = 2;
-                       }
-                       player[pn].triggerx = player[pn].tx;
-                       player[pn].triggery = player[pn].ty-1;
-               break;
-       }
-}
-
-//panning page
-void panpagemanual(map_view_t *pip, player_t *player, word pn)
-{
-       switch(player[pn].d)
-       {
-               //right movement
-               case 3:
-                       if(pip[pip[0].pan->pn].tx >= 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw < pip[pip[0].pan->pn].page->tilesw)
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       pip[pip[0].pan->pn].page->dx+=4;
-                                       modexShowPage(pip[pip[0].pan->pn].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx++; }
-                       }
-               break;
-
-               //left movement
-               case 1:
-                       if(pip[pip[0].pan->pn].tx > 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw <= pip[pip[0].pan->pn].page->tilesw)
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       pip[pip[0].pan->pn].page->dx-=4;
-                                       modexShowPage(pip[pip[0].pan->pn].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx--; }
-                       }
-               break;
-
-               //down movement
-               case 4:
-                       if(pip[pip[0].pan->pn].ty >= 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th < pip[pip[0].pan->pn].page->tilesh)
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       pip[pip[0].pan->pn].page->dy+=4;
-                                       modexShowPage(pip[pip[0].pan->pn].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty++; }
-                       }
-               break;
-
-               //up movement
-               case 0:
-                       if(pip[pip[0].pan->pn].ty > 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th <= pip[pip[0].pan->pn].page->tilesh)
-                       {
-                               if(player[pn].q<=player[pn].spt)
-                               {
-                                       pip[pip[0].pan->pn].page->dy-=4;
-                                       modexShowPage(pip[pip[0].pan->pn].page);
-                                       player[pn].q++;
-                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty--; }
-                       }
-                       break;
-       }
-       //if (player[pn].d!=2) printf("player[%u].d=%u player[%u].q=%u\n", pn, player[pn].d, pn, player[pn].q);
-}
-
-/*map_t
-allocMap(int w, int h) {
-       map_t result;
-
-       result.width =w;
-       result.height=h;
-       result.data = malloc(sizeof(byte) * w * h);
-       //result.data = (byte *)alloc_emem(((int)sizeof(byte) * w * h)/1024);
-       if(isEMS() || checkEMS())
-       {
-               XMOVE mm;
-               //emmhandle = mallocEMS(coretotalEMS());//alloc_emem((int)sizeof(map))
-               mm.length=sizeof(result);
-               mm.sourceH=0;
-               mm.sourceOff=ptr2long(&result);
-               mm.destH=emmhandle;
-               mm.destOff=0;
-               ist = move_emem(&mm);
-               if(!ist){ dealloc_emem(emmhandle); exit(5); }
-               printf("%d\n", coretotalEMS());
-       }
-
-       return result;
-}*/
-
-/*void
-initMap(map_t *map) {
-       // just a place holder to fill out an alternating pattern
-       int x, y, xx, yy;
-       int i, q;
-//     int tile = 1;
-       //if(!isEMS() || !checkEMS())
-//             map->tiles = malloc(sizeof(tiles_t));
-       //else
-       //      map->tiles = (tiles_t *)alloc_emem(sizeof(tiles_t));
-
-        //create the tile set
-       //if(!isEMS() || !checkEMS())
-//             map->tiles->data = malloc(sizeof(bitmap_t));
-       //else
-       //      map->tiles->data = (bitmap_t *)alloc_emem(sizeof(bitmap_t));
-//     map->tiles->data->width = (TILEWH);
-//     map->tiles->data->height= TILEWH;
-       //if(!isEMS() || !checkEMS())
-//             map->tiles->data->data = malloc((TILEWH*2)*TILEWH);
-       //else
-       //      map->tiles->data->data = (byte *)alloc_emem((TILEWH*2)*TILEWH);
-//     map->tiles->tileHeight = TILEWH;
-//     map->tiles->tileWidth =TILEWH;
-//     map->tiles->rows = 1;
-//     map->tiles->cols = 1;//2;
-
-       q=0;
-       //for(y=0; y<map->height; y++) {
-       //for(x=0; x<map->width; x++) {
-       i=0;
-       for(yy=0; yy<TILEWH; yy++) {
-       for(xx=0; xx<(TILEWH); xx++) {
-               //if(x<TILEWH){
-                 map->tiles->data->data[i+1] = map->data[q];//28;//0x24;
-//               printf("[%d]", map->tiles->data->data[i]);
-               //}else{
-                 //map->tiles->data->data[i] = map->data[q];//0;//0x34;
-                 //printf("]%d[==[%d]", i, map->tiles->data->data[i]);
-               //}
-               i++;
-       }
-//     printf("\n");
-       }
-//     printf("[%d]", map->data[q]);
-       q++;
-//     }
-       //printf("\n\n");
-//     }
-
-       i=0;
-       for(y=0; y<map->height; y++) {
-               for(x=0; x<map->width; x++) {
-//                     map->data[i]=255;
-                       printf("[%d]", map->data[i]);
-                       //tile = tile ? 0 : 1;
-                       i++;
-               }
-               //tile = tile ? 0 : 1;
-       }
-}*/
-
-void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid)
-{
-       word x, y;  /* coordinate for drawing */
-
-       /* increment the pixel position and update the page */
-       mv[id].page->dx += player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dx >= mv[id].dxThresh )
-       {
-       /* go forward one tile */
-       mv[id].tx++;
-       /* Snap the origin forward */
-       mv[id].page->data += 4;
-
-       mv[id].page->dx = mv[id].map->tiles->tileWidth;
-       }
-
-       /* draw the next column */
-       x= mv[0].page->sw + mv[id].map->tiles->tileWidth;
-       if(player[plid].q%4)
-               if(id==0)
-                       mapDrawCol(&mv[0], mv[0].tx + mv[0].page->tw, mv[0].ty-1, x, player, mv->page->dx);
-               else
-                       if(!pageflipflop && !pageploop)
-                               modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2));
-       mv[0].video->r=1;
-}
-
-
-void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid)
-{
-       word x, y;  /* coordinate for drawing */
-
-       /* decrement the pixel position and update the page */
-       mv[id].page->dx -= player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dx == 0)
-       {
-       /* go backward one tile */
-       mv[id].tx--;
-       /* Snap the origin backward */
-       mv[id].page->data -= 4;
-
-       mv[id].page->dx = mv[id].map->tiles->tileWidth;
-       }
-
-       /* draw the next column */
-       x= 0;
-       if(player[plid].q%4)
-               if(id==0)
-                       mapDrawCol(&mv[0], mv[0].tx - 1, mv[0].ty-1, x, player, mv->page->dx);
-               else
-                       if(!pageflipflop && !pageploop)
-                               modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2));
-       mv[0].video->r=1;
-}
-
-
-void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid)
-{
-       word x, y;  /* coordinate for drawing */
-
-       /* decrement the pixel position and update the page */
-       mv[id].page->dy -= player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dy == 0 )
-       {
-       /* go down one tile */
-       mv[id].ty--;
-       /* Snap the origin downward */
-       mv[id].page->data -= mv[id].page->pi;
-
-       mv[id].page->dy = mv[id].map->tiles->tileHeight;
-       }
-
-       /* draw the next row */
-       y= 0;
-       if(player[plid].q%3)
-               if(id==0)
-                       mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty-1, y, player, mv->page->dy);
-               else
-                       if(!pageflipflop && !pageploop)
-                               modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight);
-       mv[0].video->r=1;
-}
-
-void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid)
-{
-       word x, y;  /* coordinate for drawing */
-
-       /* increment the pixel position and update the page */
-       mv[id].page->dy += player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dy >= mv[id].dyThresh )
-       {
-       /* go down one tile */
-       mv[id].ty++;
-       /* Snap the origin downward */
-       mv[id].page->data += mv[id].page->pi;
-
-       mv[id].page->dy = mv[id].map->tiles->tileHeight;
-       }
-
-       /* draw the next row */
-       y= mv[0].page->sh + mv[id].map->tiles->tileHeight;
-       if(player[plid].q%3)
-               if(id==0)
-                       mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty+mv[0].page->th, y, player, mv->page->dy);
-               else
-                       if(!pageflipflop && !pageploop)
-                               modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight);
-       mv[0].video->r=1;
-}
-
-
-//TODO finish this wwww
-void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid)
-{
-       /* increment the pixel position and update the page */
-       mv[id].page->dx += player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dx >= mv[0].dxThresh )
-       {
-//             vga_setup_wm1_block_copy();
-//             _fmemmove(mv[id].page->data+4, mv[id].page->data, mv[id].page->pagesize);
-//             vga_restore_rm0wm0();
-               /* Snap the origin forward */
-               mv[id].page->data += 4;
-               mv[id].page->dx = mv[0].map->tiles->tileWidth;
-       }
-}
-
-void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid)
-{
-       /* decrement the pixel position and update the page */
-       mv[id].page->dx -= player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dx == 0)
-       {
-//             vga_setup_wm1_block_copy();
-//             _fmemmove(mv[id].page->data-4, mv[id].page->data, mv[id].page->pagesize);
-//             vga_restore_rm0wm0();
-               /* Snap the origin backward */
-               mv[id].page->data -= 4;
-               mv[id].page->dx = mv[0].map->tiles->tileWidth;
-       }
-}
-
-void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid)
-{
-       /* decrement the pixel position and update the page */
-       mv[id].page->dy -= player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dy == 0)
-       {
-//             vga_setup_wm1_block_copy();
-//             _fmemmove(mv[id].page->data-mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize);
-//             vga_restore_rm0wm0();
-               /* Snap the origin backward */
-               mv[id].page->data -= mv[id].page->pi;
-               mv[id].page->dy = mv[0].map->tiles->tileWidth;
-       }
-}
-
-void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid)
-{
-       /* increment the pixel position and update the page */
-       mv[id].page->dy += player[plid].speed;
-
-       /* check to see if this changes the tile */
-       if(mv[id].page->dy >= mv[0].dxThresh )
-       {
-//             vga_setup_wm1_block_copy();
-//             _fmemmove(mv[id].page->data+mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize);
-//             vga_restore_rm0wm0();
-               /* Snap the origin forward */
-               mv[id].page->data += mv[id].page->pi;
-               mv[id].page->dy = mv[0].map->tiles->tileWidth;
-       }
-}
-
-sword chkmap(map_t *map, word q)
-{
-//     bitmap_t bp;
-       static byte x[(MAPW*MAPH)+1] =
-{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 };
-/*1,   2,      3,      4,      0,      3,      3,      3,      3,      3,      3,      3,      3,      4,      1,      1,      1,      1,      1,      1,      \
-5,     6,      7,      8,      0,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-9,     10,     11,     12,     4,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-13,    14,     15,     16,     0,      1,      1,      1,      5,      8,      1,      11,     11,     1,      1,      1,      1,      1,      1,      1,      \
-0,     0,      4,      0,      0,      0,      0,      0,      8,      8,      1,      11,     11,     3,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      0,      0,      0,      0,      8,      8,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \
-1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      3,      3,      3,      1,      2,      3,      4 };*/
-       //check for failed to load map
-       if((map->width == map->height == 0) && (q>0))
-       {
-               //initiate a null map!
-               map->width=MAPW;///2;
-               map->height=MAPH;///2;
-//             map->data = malloc(((map->width*map->height)+1)*sizeof(byte));
-               map->data = &x;
-               map->tiles = malloc(sizeof(tiles_t));
-               //fix this to be far~
-//             bp = bitmapLoadPcx("data/ed.pcx");
-//             map->tiles->data = &bp;
-               map->tiles->debug_data = map->data;
-               map->tiles->tileHeight = 16;
-               map->tiles->tileWidth = 16;
-               map->tiles->rows = 1;
-               map->tiles->cols = 1;
-               map->tiles->debug_text = true;
-       }
-       else map->tiles->debug_text = false;
-       return 0;
-}
-
-//TODO: player position here
-void mapGoTo(map_view_t *mv, int tx, int ty)
-{
-       int px, py;
-       unsigned int i;
-
-       /* set up the coordinates */
-       mv[0].tx = mv[1].tx = tx;
-       mv[0].ty = mv[1].ty = ty;
-       mv[0].page->dx = mv[1].page->dx = mv[2].page->dx = mv[3].page->dx = mv->map->tiles->tileWidth;
-       mv[0].page->dy = mv[1].page->dy = mv[2].page->dy = mv[3].page->dy = mv->map->tiles->tileHeight;
-
-       /* set up the thresholds */
-       mv[0].dxThresh = mv[1].dxThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileWidth * 2;
-       mv[0].dyThresh = mv[1].dyThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileHeight * 2;
-
-       /* draw the tiles */
-       modexClearRegion(mv[0].page, 0, 0, mv[0].page->width, mv[0].page->height, 0);
-       py=0;
-       i=mv[0].ty * mv[0].map->width + mv[0].tx;
-       for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) {
-               mapDrawWRow(&mv[0], tx-1, ty, py);
-       i+=mv->map->width - tx;
-       }
-       if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height);
-//     {
-//             unsigned int k,j,o;
-//             /* fill screen with a distinctive pattern */
-//             for (k=0;k < vga_state.vga_width;k++) {
-//                     o = k >> 2;
-//                     vga_write_sequencer(0x02/*map mask*/,1 << (k&3));
-//                             for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride)
-//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!
-//             }
-//     }
-       modexCopyPageRegion(mv[3].page, mv[0].page, 0/**/, 0/**/, 0, 0, 24, 32);
-}
-
-void near
-mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y)
-{
-       word rx;
-       word ry;
-       word textx=0;
-       word texty=0;
-       //if(i==0) i=2;
-       if(i==0)
-       {
-               //wwww
-               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color!
-       }
-       else
-       {
-               rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth);
-               ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight);
-////0000printf("i=%d\n", i);
-               switch(t->debug_text)
-               {
-                       case 0:
-#ifndef TILERENDER
-                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1));
-                               //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i]));
-#else
-                               PBUFBFUN                (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));
-                               /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */
-                               //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));
-                               //modexDrawBmpRegion    (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));
-#endif
-                       break;
-                       case 1:
-                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1);
-                               //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data));
-                               /*for(texty=0; texty<2; texty++)
-                               {
-                                       for(textx=0; textx<2; textx++)
-                                       {*/
-//                                             modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data));
-/*                                     }
-                               }*/
-                       break;
-               }
-       }
-}
-
-void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset)
-{
-       word x;
-       int i;
-       poopoffset%=p[0].speed;
-//printf("y: %d\n", poopoffset);
-       /* the position within the map array */
-       i=ty * mv->map->width + tx;
-       for(x=poopoffset; x<(mv->page->sw+mv->dxThresh)/(poopoffset+1) && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) {
-       if(i>=0) {
-               /* we are in the map, so copy! */
-               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);
-       }
-       i++; /* next! */
-       }
-}
-
-void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset)
-{
-       int y;
-       int i;
-       poopoffset%=p[0].speed;
-//printf("x: %d\n", poopoffset);
-       /* location in the map array */
-       i=ty * mv->map->width + tx;
-
-       /* We'll copy all of the columns in the screen,
-          i + 1 row above and one below */
-       for(y=poopoffset; y<(mv->page->sh+mv->dyThresh)/(poopoffset+1) && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) {
-       if(i>=0) {
-               /* we are in the map, so copy away! */
-               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);
-       }
-       i += mv->map->width;
-       }
-}
-
-void mapDrawWRow(map_view_t *mv, int tx, int ty, word y)
-{
-       word x;
-       int i;
-
-       /* the position within the map array */
-       i=ty * mv->map->width + tx;
-       for(x=0; x<mv->page->sw+mv->dxThresh && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) {
-       if(i>=0) {
-               /* we are in the map, so copy! */
-               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);
-       }
-       i++; /* next! */
-       }
-}
-
-void mapDrawWCol(map_view_t *mv, int tx, int ty, word x)
-{
-       int y;
-       int i;
-
-       /* location in the map array */
-       i=ty * mv->map->width + tx;
-
-       /* We'll copy all of the columns in the screen,
-          i + 1 row above and one below */
-       for(y=0; y<mv->page->sh+mv->dyThresh && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) {
-       if(i>=0) {
-               /* we are in the map, so copy away! */
-               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);
-       }
-       i += mv->map->width;
-       }
-}
-
-/*void qclean()
-{
-       //setkb(0);
-}*/
-
-unsigned char shinku_fps_indicator_page = 2;
-boolean pageflipflop = 1;
-boolean pageploop = 1;
-
-/*     sync    */
-void shinku(global_game_variables_t *gv)
-{
-       word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen
-       word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen
-       word w = 64, h = 8, col = 7, bgcol = 0, type = 1;
-       byte o,o2,i;
-       //modexCopyPageRegion(pip[1].page, pip[2].page, 16, 16, 16, 16, (14*8)+4, 8+4);
-       /* block copy to visible RAM from offscreen */
-//     vga_setup_wm1_block_copy();
-//     modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x+w, 0, w, h);
-//     o =     *(gv->video.page[2].data); // source offscreen
-//     o2 =    *(gv->video.page[shinku_fps_indicator_page].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride)
-//     for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);
-       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */
-//     vga_restore_rm0wm0();
-       if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second))
-       {
-               sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv));
-               //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45);
-               modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee);
-               gv->kurokku.tiku=0;
-               /* block copy to visible RAM from offscreen */
-//             vga_setup_wm1_block_copy();
-//             o =     *(gv->video.page[shinku_fps_indicator_page].data); // source offscreen
-//             o2 =    *(gv->video.page[2].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride)
-//             for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);
-//             modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x, 0, w, h);
-               /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */
-//             vga_restore_rm0wm0();
-       }else //copy dat sheet
-       gv->kurokku.tiku++;
-
-       switch(gv->kurokku.fpscap)
-       {
-               case 0:
-                       //modexprint(&(gv->video.page[shinku_fps_indicator_page]), x, y+8, type, col, bgcol, "sanic!");
-                       gv->kurokku.frames_per_second=1;
-               break;
-               case 1:
-                       //turn this off if XT
-                       //modexWaitBorder();
-                       vga_wait_for_vsync();
-                       gv->kurokku.frames_per_second=60;
-               break;
-       }
-       if(pageflipflop){
-       if(gv->video.r){
-               //vga_setup_wm1_block_copy();
-               //_fmemcpy((gv->video.page[(gv->video.p)]).data, (gv->video.page[(!gv->video.p)]).data, gv->video.page[(!gv->video.p)].pagesize);
-               //vga_restore_rm0wm0();
-               if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height);
-               modexShowPage(&(gv->video.page[gv->video.p]));
-               if(!pageploop) gv->video.p=!gv->video.p;
-               gv->video.r=!gv->video.r;
-               //0000gv->video.tickclk = ((*clockw)-gv->video.startclk)/18.2;
-       }
-       }
-}
-
-void near animatePlayer(map_view_t *pip, player_t *player, word pn, sword scrollswitch)
-{
-       sword x = player[pn].x;
-       sword y = player[pn].y;
-       sword bx = x+16;        //buffer's x
-       sword by = y+16;        //buffer's y
-       word dire=32; //direction
-       sword qq; //scroll offset
-       word ls = player[pn].persist_aniframe;
-
-       switch(scrollswitch)
-       {
-               case 0:
-                       qq = 0;
-               break;
-               default:
-                       qq = ((player[pn].q)*(player[pn].speed));
-               break;
-       }
-       //x-=4;
-       y-=pip[0].map->tiles->tileHeight;
-       switch (player[pn].d)
-       {
-               case 0:
-                       //up
-                       dire*=player[pn].d;
-                       y-=qq;
-                       by-=4;
-               break;
-               case 3:
-                       // right
-                       dire*=(player[pn].d-2);
-                       x+=qq;
-                       bx+=4;
-               break;
-               case 2:
-               break;
-               case 4:
-                       //down
-                       dire*=(player[pn].d-2);
-                       y+=qq;
-                       by+=4;
-               break;
-               case 1:
-                       //left
-                       dire*=(player[pn].d+2);
-                       x-=qq;
-                       bx-=4;
-               break;
-       }
-
-#ifdef SPRITE
-#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 48, dire, 24, 32,        PLAYERBMPDATA);
-#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32,        PLAYERBMPDATA);
-#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 24, 32, PLAYERBMPDATA);
-#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32,        PLAYERBMPDATA);
-#else
-#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 2+dire);
-#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire);
-#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, dire);
-#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire);
-#endif
-       if(!pageflipflop)
-               modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 36);
-       else{
-               //copy old bg to page0
-               //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0,   20, 36);
-               //update buffer
-               //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0,   x, y,   20, 36);
-       }
-//modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height);
-       //modexCopyPageRegion(pip[3].page, pip[!(pip->video->p)].page, x-4, y-4, 0, 128, 28, 36);
-       /*modexCopyPageRegion(pip[pip->video->p].page,
- pip[!(pip->video->p)].page, x-4, y-4, x-4, y-4, 28, 36);*/
-//     else modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 40);
-       switch(ls)
-       {
-               case 1:
-                       FRAME1
-               break;
-               case 2:
-                       FRAME2
-               break;
-               case 3:
-                       FRAME3
-               break;
-               case 4:
-                       FRAME4
-               break;
-       }
-//     if(2>ls && ls>=1) { FRAME1 }else
-//     if(3>ls && ls>=2) { FRAME2 }else
-//     if(4>ls && ls>=3) { FRAME3 }else
-//     if(5>ls && ls>=4) { FRAME4 }
-       //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 24, 32);
-       //printf("x=%d  y=%d    bx=%d           by=%d\n", x, y, bx, by);
-       pip->video->r=1;
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+/*\r
+       scroll16 library~\r
+*/\r
+#include "src/lib/scroll16.h"\r
+\r
+void walk(map_view_t *pip, player_t *player, word pn)\r
+{\r
+       #define INC_PER_FRAME if(player[pn].q&1) player[pn].persist_aniframe++; if(player[pn].persist_aniframe>4) player[pn].persist_aniframe = 1;\r
+       //printf("player[%d].d=%d\n", pn, player[pn].d);\r
+       switch(player[pn].d)\r
+       {\r
+               //no direction\r
+               case 2:\r
+                       //0000pip[0].video->startclk = (*clockw);\r
+               break;\r
+               //right movement\r
+               case 3:\r
+                       //printf("pip[0].page->tilesw=%d        ", pip[0].page->tilesw); printf("pip[0].page->tw=%d\n", pip[0].page->tw);\r
+                       if(pip[0].tx >= 0 && pip[0].tx+pip[0].page->tw < pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx &&\r
+                       !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY))      //collision detection!\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       animatePlayer(pip, player, pn, 1);\r
+                                       ScrollRight(pip, player, 3, pn);\r
+                                       ScrollRight(pip, player, 2, pn);\r
+                                       mapScrollRight(pip, player, !(pip[0].video->p), pn);\r
+                                       mapScrollRight(pip, player, (pip[0].video->p), pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; }\r
+                       }\r
+                       else if(player[pn].tx < pip[0].map->width && !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY))\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       player[pn].x+=(player[pn].speed);\r
+                                       animatePlayer(pip, player, pn, 0);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; }\r
+                       }\r
+                       else\r
+                       {\r
+                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32);\r
+#ifdef SPRITE\r
+                               PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 24, 32, PLAYERBMPDATA);\r
+#else\r
+                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 14);\r
+#endif\r
+                               if(!pageflipflop) modexShowPage(pip[1].page);\r
+                               player[pn].d = 2;\r
+                       }\r
+                       player[pn].triggerx = player[pn].tx+1;\r
+                       player[pn].triggery = player[pn].ty;\r
+               break;\r
+\r
+               //left movement\r
+               case 1:\r
+                       if(pip[0].tx > 0 && pip[0].tx+pip[0].page->tw <= pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx &&\r
+                       !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY))    //collision detection!\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       animatePlayer(pip, player, pn, 1);\r
+                                       ScrollLeft(pip, player, 3, pn);\r
+                                       ScrollLeft(pip, player, 2, pn);\r
+                                       mapScrollLeft(pip, player, !(pip[0].video->p), pn);\r
+                                       mapScrollLeft(pip, player, (pip[0].video->p), pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; }\r
+                       }\r
+                       else if(player[pn].tx > 1 && !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY))\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       player[pn].x-=(player[pn].speed);\r
+                                       animatePlayer(pip, player, pn, 0);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; }\r
+                       }\r
+                       else\r
+                       {\r
+                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32);\r
+#ifdef SPRITE\r
+                               PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 96, 24, 32, PLAYERBMPDATA);\r
+#else\r
+                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 10);\r
+#endif\r
+                               if(!pageflipflop) modexShowPage(pip[1].page);\r
+                               player[pn].d = 2;\r
+                       }\r
+                       player[pn].triggerx = player[pn].tx-1;\r
+                       player[pn].triggery = player[pn].ty;\r
+               break;\r
+\r
+               //down movement\r
+               case 4:\r
+                       if(pip[0].ty >= 0 && pip[0].ty+pip[0].page->th < pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny &&\r
+                       !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY))      //collision detection!\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       animatePlayer(pip, player, pn, 1);\r
+                                       ScrollDown(pip, player, 3, pn);\r
+                                       ScrollDown(pip, player, 2, pn);\r
+                                       mapScrollDown(pip, player, !(pip[0].video->p), pn);\r
+                                       mapScrollDown(pip, player, (pip[0].video->p), pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; }\r
+                       }\r
+                       else if(player[pn].ty < pip[0].map->height && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY))\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       player[pn].y+=(player[pn].speed);\r
+                                       animatePlayer(pip, player, pn, 0);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; }\r
+                       }\r
+                       else\r
+                       {\r
+                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32);\r
+#ifdef SPRITE\r
+                               PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 64, 24, 32, PLAYERBMPDATA);\r
+#else\r
+                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 9);\r
+#endif\r
+                               if(!pageflipflop) modexShowPage(pip[1].page);\r
+                               player[pn].d = 2;\r
+                       }\r
+                       player[pn].triggerx = player[pn].tx;\r
+                       player[pn].triggery = player[pn].ty+1;\r
+               break;\r
+\r
+               //up movement\r
+               case 0:\r
+                       if(pip[0].ty > 0 && pip[0].ty+pip[0].page->th <= pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny &&\r
+                       !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY))    //collision detection!\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       animatePlayer(pip, player, pn, 1);\r
+                                       ScrollUp(pip, player, 3, pn);\r
+                                       ScrollUp(pip, player, 2, pn);\r
+                                       mapScrollUp(pip, player, !(pip[0].video->p), pn);\r
+                                       mapScrollUp(pip, player, (pip[0].video->p), pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                                       //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; }\r
+                       }\r
+                       else if(player[pn].ty > 1 && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX &&  player[pn].ty-1 == TRIGGY))\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       INC_PER_FRAME;\r
+                                       player[pn].y-=(player[pn].speed);\r
+                                       animatePlayer(pip, player, 0, pn);\r
+                                       if(!pageflipflop) modexShowPage(pip[1].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; }\r
+                       }\r
+                       else\r
+                       {\r
+                               if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32);\r
+#ifdef SPRITE\r
+                               PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 0, 24, 32, PLAYERBMPDATA);\r
+#else\r
+                               modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 12);\r
+#endif\r
+                               if(!pageflipflop) modexShowPage(pip[1].page);\r
+                               player[pn].d = 2;\r
+                       }\r
+                       player[pn].triggerx = player[pn].tx;\r
+                       player[pn].triggery = player[pn].ty-1;\r
+               break;\r
+       }\r
+}\r
+\r
+//panning page\r
+void panpagemanual(map_view_t *pip, player_t *player, word pn)\r
+{\r
+       switch(player[pn].d)\r
+       {\r
+               //right movement\r
+               case 3:\r
+                       if(pip[pip[0].pan->pn].tx >= 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw < pip[pip[0].pan->pn].page->tilesw)\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       pip[pip[0].pan->pn].page->dx+=4;\r
+                                       modexShowPage(pip[pip[0].pan->pn].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx++; }\r
+                       }\r
+               break;\r
+\r
+               //left movement\r
+               case 1:\r
+                       if(pip[pip[0].pan->pn].tx > 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw <= pip[pip[0].pan->pn].page->tilesw)\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       pip[pip[0].pan->pn].page->dx-=4;\r
+                                       modexShowPage(pip[pip[0].pan->pn].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx--; }\r
+                       }\r
+               break;\r
+\r
+               //down movement\r
+               case 4:\r
+                       if(pip[pip[0].pan->pn].ty >= 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th < pip[pip[0].pan->pn].page->tilesh)\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       pip[pip[0].pan->pn].page->dy+=4;\r
+                                       modexShowPage(pip[pip[0].pan->pn].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty++; }\r
+                       }\r
+               break;\r
+\r
+               //up movement\r
+               case 0:\r
+                       if(pip[pip[0].pan->pn].ty > 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th <= pip[pip[0].pan->pn].page->tilesh)\r
+                       {\r
+                               if(player[pn].q<=player[pn].spt)\r
+                               {\r
+                                       pip[pip[0].pan->pn].page->dy-=4;\r
+                                       modexShowPage(pip[pip[0].pan->pn].page);\r
+                                       player[pn].q++;\r
+                               } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty--; }\r
+                       }\r
+                       break;\r
+       }\r
+       //if (player[pn].d!=2) printf("player[%u].d=%u player[%u].q=%u\n", pn, player[pn].d, pn, player[pn].q);\r
+}\r
+\r
+/*map_t\r
+allocMap(int w, int h) {\r
+       map_t result;\r
+\r
+       result.width =w;\r
+       result.height=h;\r
+       result.data = malloc(sizeof(byte) * w * h);\r
+       //result.data = (byte *)alloc_emem(((int)sizeof(byte) * w * h)/1024);\r
+       if(isEMS() || checkEMS())\r
+       {\r
+               XMOVE mm;\r
+               //emmhandle = mallocEMS(coretotalEMS());//alloc_emem((int)sizeof(map))\r
+               mm.length=sizeof(result);\r
+               mm.sourceH=0;\r
+               mm.sourceOff=ptr2long(&result);\r
+               mm.destH=emmhandle;\r
+               mm.destOff=0;\r
+               ist = move_emem(&mm);\r
+               if(!ist){ dealloc_emem(emmhandle); exit(5); }\r
+               printf("%d\n", coretotalEMS());\r
+       }\r
+\r
+       return result;\r
+}*/\r
+\r
+/*void\r
+initMap(map_t *map) {\r
+       // just a place holder to fill out an alternating pattern\r
+       int x, y, xx, yy;\r
+       int i, q;\r
+//     int tile = 1;\r
+       //if(!isEMS() || !checkEMS())\r
+//             map->tiles = malloc(sizeof(tiles_t));\r
+       //else\r
+       //      map->tiles = (tiles_t *)alloc_emem(sizeof(tiles_t));\r
+\r
+        //create the tile set\r
+       //if(!isEMS() || !checkEMS())\r
+//             map->tiles->data = malloc(sizeof(bitmap_t));\r
+       //else\r
+       //      map->tiles->data = (bitmap_t *)alloc_emem(sizeof(bitmap_t));\r
+//     map->tiles->data->width = (TILEWH);\r
+//     map->tiles->data->height= TILEWH;\r
+       //if(!isEMS() || !checkEMS())\r
+//             map->tiles->data->data = malloc((TILEWH*2)*TILEWH);\r
+       //else\r
+       //      map->tiles->data->data = (byte *)alloc_emem((TILEWH*2)*TILEWH);\r
+//     map->tiles->tileHeight = TILEWH;\r
+//     map->tiles->tileWidth =TILEWH;\r
+//     map->tiles->rows = 1;\r
+//     map->tiles->cols = 1;//2;\r
+\r
+       q=0;\r
+       //for(y=0; y<map->height; y++) {\r
+       //for(x=0; x<map->width; x++) {\r
+       i=0;\r
+       for(yy=0; yy<TILEWH; yy++) {\r
+       for(xx=0; xx<(TILEWH); xx++) {\r
+               //if(x<TILEWH){\r
+                 map->tiles->data->data[i+1] = map->data[q];//28;//0x24;\r
+//               printf("[%d]", map->tiles->data->data[i]);\r
+               //}else{\r
+                 //map->tiles->data->data[i] = map->data[q];//0;//0x34;\r
+                 //printf("]%d[==[%d]", i, map->tiles->data->data[i]);\r
+               //}\r
+               i++;\r
+       }\r
+//     printf("\n");\r
+       }\r
+//     printf("[%d]", map->data[q]);\r
+       q++;\r
+//     }\r
+       //printf("\n\n");\r
+//     }\r
+\r
+       i=0;\r
+       for(y=0; y<map->height; y++) {\r
+               for(x=0; x<map->width; x++) {\r
+//                     map->data[i]=255;\r
+                       printf("[%d]", map->data[i]);\r
+                       //tile = tile ? 0 : 1;\r
+                       i++;\r
+               }\r
+               //tile = tile ? 0 : 1;\r
+       }\r
+}*/\r
+\r
+void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* increment the pixel position and update the page */\r
+       mv[id].page->dx += player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dx >= mv[id].dxThresh )\r
+       {\r
+       /* go forward one tile */\r
+       mv[id].tx++;\r
+       /* Snap the origin forward */\r
+       mv[id].page->data += 4;\r
+\r
+       mv[id].page->dx = mv[id].map->tiles->tileWidth;\r
+       }\r
+\r
+       /* draw the next column */\r
+       x= mv[0].page->sw + mv[id].map->tiles->tileWidth;\r
+       if(player[plid].q%4)\r
+               if(id==0)\r
+                       mapDrawCol(&mv[0], mv[0].tx + mv[0].page->tw, mv[0].ty-1, x, player, mv->page->dx);\r
+               else\r
+                       if(!pageflipflop && !pageploop)\r
+                               modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2));\r
+       mv[0].video->r=1;\r
+}\r
+\r
+\r
+void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* decrement the pixel position and update the page */\r
+       mv[id].page->dx -= player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dx == 0)\r
+       {\r
+       /* go backward one tile */\r
+       mv[id].tx--;\r
+       /* Snap the origin backward */\r
+       mv[id].page->data -= 4;\r
+\r
+       mv[id].page->dx = mv[id].map->tiles->tileWidth;\r
+       }\r
+\r
+       /* draw the next column */\r
+       x= 0;\r
+       if(player[plid].q%4)\r
+               if(id==0)\r
+                       mapDrawCol(&mv[0], mv[0].tx - 1, mv[0].ty-1, x, player, mv->page->dx);\r
+               else\r
+                       if(!pageflipflop && !pageploop)\r
+                               modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2));\r
+       mv[0].video->r=1;\r
+}\r
+\r
+\r
+void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* decrement the pixel position and update the page */\r
+       mv[id].page->dy -= player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dy == 0 )\r
+       {\r
+       /* go down one tile */\r
+       mv[id].ty--;\r
+       /* Snap the origin downward */\r
+       mv[id].page->data -= mv[id].page->pi;\r
+\r
+       mv[id].page->dy = mv[id].map->tiles->tileHeight;\r
+       }\r
+\r
+       /* draw the next row */\r
+       y= 0;\r
+       if(player[plid].q%3)\r
+               if(id==0)\r
+                       mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty-1, y, player, mv->page->dy);\r
+               else\r
+                       if(!pageflipflop && !pageploop)\r
+                               modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight);\r
+       mv[0].video->r=1;\r
+}\r
+\r
+void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* increment the pixel position and update the page */\r
+       mv[id].page->dy += player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dy >= mv[id].dyThresh )\r
+       {\r
+       /* go down one tile */\r
+       mv[id].ty++;\r
+       /* Snap the origin downward */\r
+       mv[id].page->data += mv[id].page->pi;\r
+\r
+       mv[id].page->dy = mv[id].map->tiles->tileHeight;\r
+       }\r
+\r
+       /* draw the next row */\r
+       y= mv[0].page->sh + mv[id].map->tiles->tileHeight;\r
+       if(player[plid].q%3)\r
+               if(id==0)\r
+                       mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty+mv[0].page->th, y, player, mv->page->dy);\r
+               else\r
+                       if(!pageflipflop && !pageploop)\r
+                               modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight);\r
+       mv[0].video->r=1;\r
+}\r
+\r
+\r
+//TODO finish this wwww\r
+void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       /* increment the pixel position and update the page */\r
+       mv[id].page->dx += player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dx >= mv[0].dxThresh )\r
+       {\r
+//             vga_setup_wm1_block_copy();\r
+//             _fmemmove(mv[id].page->data+4, mv[id].page->data, mv[id].page->pagesize);\r
+//             vga_restore_rm0wm0();\r
+               /* Snap the origin forward */\r
+               mv[id].page->data += 4;\r
+               mv[id].page->dx = mv[0].map->tiles->tileWidth;\r
+       }\r
+}\r
+\r
+void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       /* decrement the pixel position and update the page */\r
+       mv[id].page->dx -= player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dx == 0)\r
+       {\r
+//             vga_setup_wm1_block_copy();\r
+//             _fmemmove(mv[id].page->data-4, mv[id].page->data, mv[id].page->pagesize);\r
+//             vga_restore_rm0wm0();\r
+               /* Snap the origin backward */\r
+               mv[id].page->data -= 4;\r
+               mv[id].page->dx = mv[0].map->tiles->tileWidth;\r
+       }\r
+}\r
+\r
+void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       /* decrement the pixel position and update the page */\r
+       mv[id].page->dy -= player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dy == 0)\r
+       {\r
+//             vga_setup_wm1_block_copy();\r
+//             _fmemmove(mv[id].page->data-mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize);\r
+//             vga_restore_rm0wm0();\r
+               /* Snap the origin backward */\r
+               mv[id].page->data -= mv[id].page->pi;\r
+               mv[id].page->dy = mv[0].map->tiles->tileWidth;\r
+       }\r
+}\r
+\r
+void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid)\r
+{\r
+       /* increment the pixel position and update the page */\r
+       mv[id].page->dy += player[plid].speed;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv[id].page->dy >= mv[0].dxThresh )\r
+       {\r
+//             vga_setup_wm1_block_copy();\r
+//             _fmemmove(mv[id].page->data+mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize);\r
+//             vga_restore_rm0wm0();\r
+               /* Snap the origin forward */\r
+               mv[id].page->data += mv[id].page->pi;\r
+               mv[id].page->dy = mv[0].map->tiles->tileWidth;\r
+       }\r
+}\r
+\r
+sword chkmap(map_t *map, word q)\r
+{\r
+//     bitmap_t bp;\r
+       static byte x[(MAPW*MAPH)+1] =\r
+{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 };\r
+/*1,   2,      3,      4,      0,      3,      3,      3,      3,      3,      3,      3,      3,      4,      1,      1,      1,      1,      1,      1,      \\r
+5,     6,      7,      8,      0,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+9,     10,     11,     12,     4,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+13,    14,     15,     16,     0,      1,      1,      1,      5,      8,      1,      11,     11,     1,      1,      1,      1,      1,      1,      1,      \\r
+0,     0,      4,      0,      0,      0,      0,      0,      8,      8,      1,      11,     11,     3,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      0,      0,      0,      0,      8,      8,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      3,      3,      3,      1,      2,      3,      4 };*/\r
+       //check for failed to load map\r
+       if((map->width == map->height == 0) && (q>0))\r
+       {\r
+               //initiate a null map!\r
+               map->width=MAPW;///2;\r
+               map->height=MAPH;///2;\r
+//             map->data = malloc(((map->width*map->height)+1)*sizeof(byte));\r
+               map->data = &x;\r
+               map->tiles = malloc(sizeof(tiles_t));\r
+               //fix this to be far~\r
+//             bp = bitmapLoadPcx("data/ed.pcx");\r
+//             map->tiles->data = &bp;\r
+               map->tiles->debug_data = map->data;\r
+               map->tiles->tileHeight = 16;\r
+               map->tiles->tileWidth = 16;\r
+               map->tiles->rows = 1;\r
+               map->tiles->cols = 1;\r
+               map->tiles->debug_text = true;\r
+       }\r
+       else map->tiles->debug_text = false;\r
+       return 0;\r
+}\r
+\r
+//TODO: player position here\r
+void mapGoTo(map_view_t *mv, int tx, int ty)\r
+{\r
+       int px, py;\r
+       unsigned int i;\r
+\r
+       /* set up the coordinates */\r
+       mv[0].tx = mv[1].tx = tx;\r
+       mv[0].ty = mv[1].ty = ty;\r
+       mv[0].page->dx = mv[1].page->dx = mv[2].page->dx = mv[3].page->dx = mv->map->tiles->tileWidth;\r
+       mv[0].page->dy = mv[1].page->dy = mv[2].page->dy = mv[3].page->dy = mv->map->tiles->tileHeight;\r
+\r
+       /* set up the thresholds */\r
+       mv[0].dxThresh = mv[1].dxThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileWidth * 2;\r
+       mv[0].dyThresh = mv[1].dyThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileHeight * 2;\r
+\r
+       /* draw the tiles */\r
+       modexClearRegion(mv[0].page, 0, 0, mv[0].page->width, mv[0].page->height, 0);\r
+       py=0;\r
+       i=mv[0].ty * mv[0].map->width + mv[0].tx;\r
+       for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) {\r
+               mapDrawWRow(&mv[0], tx-1, ty, py);\r
+       i+=mv->map->width - tx;\r
+       }\r
+       if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height);\r
+//     {\r
+//             unsigned int k,j,o;\r
+//             /* fill screen with a distinctive pattern */\r
+//             for (k=0;k < vga_state.vga_width;k++) {\r
+//                     o = k >> 2;\r
+//                     vga_write_sequencer(0x02/*map mask*/,1 << (k&3));\r
+//                             for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride)\r
+//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!\r
+//             }\r
+//     }\r
+       modexCopyPageRegion(mv[3].page, mv[0].page, 0/**/, 0/**/, 0, 0, 24, 32);\r
+}\r
+\r
+void near\r
+mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y)\r
+{\r
+       word rx;\r
+       word ry;\r
+       word textx=0;\r
+       word texty=0;\r
+       //if(i==0) i=2;\r
+       if(i==0)\r
+       {\r
+               //wwww\r
+               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color!\r
+       }\r
+       else\r
+       {\r
+               rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth);\r
+               ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight);\r
+////0000printf("i=%d\n", i);\r
+               switch(t->debug_text)\r
+               {\r
+                       case 0:\r
+#ifndef TILERENDER\r
+                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1));\r
+                               //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i]));\r
+#else\r
+                               PBUFBFUN                (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));\r
+                               /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */\r
+                               //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));\r
+                               //modexDrawBmpRegion    (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));\r
+#endif\r
+                       break;\r
+                       case 1:\r
+                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1);\r
+                               //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data));\r
+                               /*for(texty=0; texty<2; texty++)\r
+                               {\r
+                                       for(textx=0; textx<2; textx++)\r
+                                       {*/\r
+//                                             modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data));\r
+/*                                     }\r
+                               }*/\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset)\r
+{\r
+       word x;\r
+       int i;\r
+       poopoffset%=p[0].speed;\r
+//printf("y: %d\n", poopoffset);\r
+       /* the position within the map array */\r
+       i=ty * mv->map->width + tx;\r
+       for(x=poopoffset; x<(mv->page->sw+mv->dxThresh)/(poopoffset+1) && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i++; /* next! */\r
+       }\r
+}\r
+\r
+void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset)\r
+{\r
+       int y;\r
+       int i;\r
+       poopoffset%=p[0].speed;\r
+//printf("x: %d\n", poopoffset);\r
+       /* location in the map array */\r
+       i=ty * mv->map->width + tx;\r
+\r
+       /* We'll copy all of the columns in the screen,\r
+          i + 1 row above and one below */\r
+       for(y=poopoffset; y<(mv->page->sh+mv->dyThresh)/(poopoffset+1) && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy away! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i += mv->map->width;\r
+       }\r
+}\r
+\r
+void mapDrawWRow(map_view_t *mv, int tx, int ty, word y)\r
+{\r
+       word x;\r
+       int i;\r
+\r
+       /* the position within the map array */\r
+       i=ty * mv->map->width + tx;\r
+       for(x=0; x<mv->page->sw+mv->dxThresh && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i++; /* next! */\r
+       }\r
+}\r
+\r
+void mapDrawWCol(map_view_t *mv, int tx, int ty, word x)\r
+{\r
+       int y;\r
+       int i;\r
+\r
+       /* location in the map array */\r
+       i=ty * mv->map->width + tx;\r
+\r
+       /* We'll copy all of the columns in the screen,\r
+          i + 1 row above and one below */\r
+       for(y=0; y<mv->page->sh+mv->dyThresh && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy away! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i += mv->map->width;\r
+       }\r
+}\r
+\r
+/*void qclean()\r
+{\r
+       //setkb(0);\r
+}*/\r
+\r
+unsigned char shinku_fps_indicator_page = 2;\r
+boolean pageflipflop = 1;\r
+boolean pageploop = 1;\r
+\r
+/*     sync    */\r
+void shinku(global_game_variables_t *gv)\r
+{\r
+       word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen\r
+       word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen\r
+       word w = 64, h = 8, col = 7, bgcol = 0, type = 1;\r
+       byte o,o2,i;\r
+       //modexCopyPageRegion(pip[1].page, pip[2].page, 16, 16, 16, 16, (14*8)+4, 8+4);\r
+       /* block copy to visible RAM from offscreen */\r
+//     vga_setup_wm1_block_copy();\r
+//     modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x+w, 0, w, h);\r
+//     o =     *(gv->video.page[2].data); // source offscreen\r
+//     o2 =    *(gv->video.page[shinku_fps_indicator_page].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride)\r
+//     for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);\r
+       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */\r
+//     vga_restore_rm0wm0();\r
+       if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second))\r
+       {\r
+               sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv));\r
+               //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45);\r
+               modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee);\r
+               gv->kurokku.tiku=0;\r
+               /* block copy to visible RAM from offscreen */\r
+//             vga_setup_wm1_block_copy();\r
+//             o =     *(gv->video.page[shinku_fps_indicator_page].data); // source offscreen\r
+//             o2 =    *(gv->video.page[2].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride)\r
+//             for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);\r
+//             modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x, 0, w, h);\r
+               /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */\r
+//             vga_restore_rm0wm0();\r
+       }else //copy dat sheet\r
+       gv->kurokku.tiku++;\r
+\r
+       switch(gv->kurokku.fpscap)\r
+       {\r
+               case 0:\r
+                       //modexprint(&(gv->video.page[shinku_fps_indicator_page]), x, y+8, type, col, bgcol, "sanic!");\r
+                       gv->kurokku.frames_per_second=1;\r
+               break;\r
+               case 1:\r
+                       //turn this off if XT\r
+                       //modexWaitBorder();\r
+                       vga_wait_for_vsync();\r
+                       gv->kurokku.frames_per_second=60;\r
+               break;\r
+       }\r
+       if(pageflipflop){\r
+       if(gv->video.r){\r
+               //vga_setup_wm1_block_copy();\r
+               //_fmemcpy((gv->video.page[(gv->video.p)]).data, (gv->video.page[(!gv->video.p)]).data, gv->video.page[(!gv->video.p)].pagesize);\r
+               //vga_restore_rm0wm0();\r
+               if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height);\r
+               modexShowPage(&(gv->video.page[gv->video.p]));\r
+               if(!pageploop) gv->video.p=!gv->video.p;\r
+               gv->video.r=!gv->video.r;\r
+               //0000gv->video.tickclk = ((*clockw)-gv->video.startclk)/18.2;\r
+       }\r
+       }\r
+}\r
+\r
+void near animatePlayer(map_view_t *pip, player_t *player, word pn, sword scrollswitch)\r
+{\r
+       sword x = player[pn].x;\r
+       sword y = player[pn].y;\r
+       sword bx = x+16;        //buffer's x\r
+       sword by = y+16;        //buffer's y\r
+       word dire=32; //direction\r
+       sword qq; //scroll offset\r
+       word ls = player[pn].persist_aniframe;\r
+\r
+       switch(scrollswitch)\r
+       {\r
+               case 0:\r
+                       qq = 0;\r
+               break;\r
+               default:\r
+                       qq = ((player[pn].q)*(player[pn].speed));\r
+               break;\r
+       }\r
+       //x-=4;\r
+       y-=pip[0].map->tiles->tileHeight;\r
+       switch (player[pn].d)\r
+       {\r
+               case 0:\r
+                       //up\r
+                       dire*=player[pn].d;\r
+                       y-=qq;\r
+                       by-=4;\r
+               break;\r
+               case 3:\r
+                       // right\r
+                       dire*=(player[pn].d-2);\r
+                       x+=qq;\r
+                       bx+=4;\r
+               break;\r
+               case 2:\r
+               break;\r
+               case 4:\r
+                       //down\r
+                       dire*=(player[pn].d-2);\r
+                       y+=qq;\r
+                       by+=4;\r
+               break;\r
+               case 1:\r
+                       //left\r
+                       dire*=(player[pn].d+2);\r
+                       x-=qq;\r
+                       bx-=4;\r
+               break;\r
+       }\r
+\r
+#ifdef SPRITE\r
+#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 48, dire, 24, 32,        PLAYERBMPDATA);\r
+#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32,        PLAYERBMPDATA);\r
+#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 24, 32, PLAYERBMPDATA);\r
+#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32,        PLAYERBMPDATA);\r
+#else\r
+#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 2+dire);\r
+#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire);\r
+#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, dire);\r
+#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire);\r
+#endif\r
+       if(!pageflipflop)\r
+               modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 36);\r
+       else{\r
+               //copy old bg to page0\r
+               //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0,   20, 36);\r
+               //update buffer\r
+               //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0,   x, y,   20, 36);\r
+       }\r
+//modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height);\r
+       //modexCopyPageRegion(pip[3].page, pip[!(pip->video->p)].page, x-4, y-4, 0, 128, 28, 36);\r
+       /*modexCopyPageRegion(pip[pip->video->p].page,\r
+ pip[!(pip->video->p)].page, x-4, y-4, x-4, y-4, 28, 36);*/\r
+//     else modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 40);\r
+       switch(ls)\r
+       {\r
+               case 1:\r
+                       FRAME1\r
+               break;\r
+               case 2:\r
+                       FRAME2\r
+               break;\r
+               case 3:\r
+                       FRAME3\r
+               break;\r
+               case 4:\r
+                       FRAME4\r
+               break;\r
+       }\r
+//     if(2>ls && ls>=1) { FRAME1 }else\r
+//     if(3>ls && ls>=2) { FRAME2 }else\r
+//     if(4>ls && ls>=3) { FRAME3 }else\r
+//     if(5>ls && ls>=4) { FRAME4 }\r
+       //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 24, 32);\r
+       //printf("x=%d  y=%d    bx=%d           by=%d\n", x, y, bx, by);\r
+       pip->video->r=1;\r
+}\r
index a3402a02801377ec6ee892cb9c7452a1aa20d9bf..1f60967087e3bcb74d3a56b1aa192096f835868a 100755 (executable)
@@ -1,95 +1,96 @@
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __SCROLL16_H_
-#define __SCROLL16_H_
-
-#include "src/lib/16_head.h"
-#include "src/lib/bakapee.h"
-#include "src/lib/modex16.h"
-#include "src/lib/16_in.h"
-#include "src/lib/bitmap.h"
-#include "src/lib/mapread.h" //map is loaded here www
-#include "src/lib/16_timer.h"
-#include "src/lib/wcpu/wcpu.h"
-
-#include <hw/cpu/cpu.h>
-#include <hw/dos/dos.h>
-#include <hw/vga/vga.h>
-#include <hw/vga/vrl.h>
-
-#define SPRITE
-//#define TILERENDER
-
-//modexDrawSpritePBufRegion
-//modexDrawBmpPBufRegion
-#define PBUFSFUN               modexDrawSpriteRegion
-#define PBUFBFUN               modexDrawBmpRegion
-#define PLAYERBMPDATA  player[pn].data
-
-typedef struct {
-       map_t *map;
-       page_t *page;
-       int tx; //appears to be the top left tile position on the viewable screen map
-       int ty; //appears to be the top left tile position on the viewable screen map
-       word dxThresh; //????
-       word dyThresh; //????
-       video_t *video; //pointer to game variables of the video
-       pan_t *pan;             //pointer the the page panning debug system
-} map_view_t;
-
-typedef struct
-{
-       map_view_t *mv;
-} map_view_db_t;
-
-//for null map!
-#define MAPW   40
-#define MAPH   30
-
-extern boolean pageflipflop, pageploop;
-extern unsigned char shinku_fps_indicator_page;
-
-//map_t allocMap(int w, int h);
-//void initMap(map_t *map);
-void walk(map_view_t *pip, player_t *player, word pn);
-void panpagemanual(map_view_t *pip,  player_t *player, word pn);
-void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid);
-void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid);
-void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid);
-void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid);
-void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid);
-void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid);
-void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid);
-void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid);
-sword chkmap(map_t *map, word q);
-void mapGoTo(map_view_t *mv, int tx, int ty);
-void near mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y);
-void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset);
-void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset);
-void mapDrawWRow(map_view_t *mv, int tx, int ty, word y);
-void mapDrawWCol(map_view_t *mv, int tx, int ty, word x);
-//void qclean();
-void shinku(global_game_variables_t *gv);
-void near animatePlayer(map_view_t *pip, player_t *player, word playnum, sword scrollswitch);
-
-#endif /*__SCROLL16_H_*/
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#ifndef __SCROLL16_H_\r
+#define __SCROLL16_H_\r
+\r
+#include "src/lib/16_head.h"\r
+#include "src/lib/bakapee.h"\r
+#include "src/lib/modex16.h"\r
+#include "src/lib/16_in.h"\r
+#include "src/lib/bitmap.h"\r
+#include "src/lib/mapread.h" //map is loaded here www\r
+#include "src/lib/16_timer.h"\r
+#include "src/lib/wcpu/wcpu.h"\r
+#include "src/lib/16_tail.h"\r
+\r
+#include <hw/cpu/cpu.h>\r
+#include <hw/dos/dos.h>\r
+#include <hw/vga/vga.h>\r
+#include <hw/vga/vrl.h>\r
+\r
+#define SPRITE\r
+//#define TILERENDER\r
+\r
+//modexDrawSpritePBufRegion\r
+//modexDrawBmpPBufRegion\r
+#define PBUFSFUN               modexDrawSpriteRegion\r
+#define PBUFBFUN               modexDrawBmpRegion\r
+#define PLAYERBMPDATA  player[pn].data\r
+\r
+typedef struct {\r
+       map_t *map;\r
+       page_t *page;\r
+       int tx; //appears to be the top left tile position on the viewable screen map\r
+       int ty; //appears to be the top left tile position on the viewable screen map\r
+       word dxThresh; //????\r
+       word dyThresh; //????\r
+       video_t *video; //pointer to game variables of the video\r
+       pan_t *pan;             //pointer the the page panning debug system\r
+} map_view_t;\r
+\r
+typedef struct\r
+{\r
+       map_view_t *mv;\r
+} map_view_db_t;\r
+\r
+//for null map!\r
+#define MAPW   40\r
+#define MAPH   30\r
+\r
+extern boolean pageflipflop, pageploop;\r
+extern unsigned char shinku_fps_indicator_page;\r
+\r
+//map_t allocMap(int w, int h);\r
+//void initMap(map_t *map);\r
+void walk(map_view_t *pip, player_t *player, word pn);\r
+void panpagemanual(map_view_t *pip,  player_t *player, word pn);\r
+void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid);\r
+void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid);\r
+void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid);\r
+void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid);\r
+void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid);\r
+void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid);\r
+void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid);\r
+void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid);\r
+sword chkmap(map_t *map, word q);\r
+void mapGoTo(map_view_t *mv, int tx, int ty);\r
+void near mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y);\r
+void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset);\r
+void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset);\r
+void mapDrawWRow(map_view_t *mv, int tx, int ty, word y);\r
+void mapDrawWCol(map_view_t *mv, int tx, int ty, word x);\r
+//void qclean();\r
+void shinku(global_game_variables_t *gv);\r
+void near animatePlayer(map_view_t *pip, player_t *player, word playnum, sword scrollswitch);\r
+\r
+#endif /*__SCROLL16_H_*/\r
index fdf96a278d241d0c9228e3aad7e1a489f4e2e993..32aaed26247dff50ca141cc0ad730a5930ceb65f 100755 (executable)
@@ -120,7 +120,7 @@ typedef struct
 } pan_t;\r
 \r
 //video\r
-#define NUMCHUNKS      3016    //keen\r
+#define NUMCHUNKS      416     //keen\r
 \r
 typedef struct\r
 {\r
@@ -135,6 +135,12 @@ typedef struct
        //0000word startclk; float clk, tickclk;        //timer\r
 } video_t;\r
 \r
+//from 16_mm\r
+//==========================================================================\r
+\r
+#define MAXBLOCKS              1024\r
+#define MAXUMBS                12\r
+\r
 typedef struct mmblockstruct\r
 {\r
        word    start,length;\r
@@ -146,15 +152,10 @@ typedef struct mmblockstruct
        struct mmblockstruct far *next;\r
 } mmblocktype;\r
 \r
-//from 16_mm\r
-//==========================================================================\r
-\r
-#define MAXBLOCKS              1024\r
-#define MAXUMBS                12\r
-\r
 typedef struct\r
 {\r
        dword   nearheap,farheap,EMSmem,XMSmem,mainmem;\r
+//     boolean         PMStarted, MainPresent, EMSPresent, XMSPresent;\r
 } mminfotype;\r
 \r
 typedef struct\r
@@ -169,10 +170,9 @@ typedef struct
 #ifdef __WATCOMC__\r
        void __near     *nearheap;\r
 #endif\r
-       //byte          EMS_status;\r
-       unsigned        totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;\r
-       unsigned int EMSVer;\r
+       unsigned int            EMSVer;\r
        word numUMBs,UMBbase[MAXUMBS];\r
+       word                    totalEMSpages, freeEMSpages, EMSpagesmapped, EMSHandle, EMSPageFrame;\r
        //dword numUMBs,UMBbase[MAXUMBS];\r
        //huge mmblocktype      huge mmblocks[MAXBLOCKS],huge *mmhead,huge *mmfree,huge *mmrover,huge *mmnew;\r
        mmblocktype     far mmblocks[MAXBLOCKS],far *mmhead,far *mmfree,far *mmrover,far *mmnew;\r
@@ -180,6 +180,118 @@ typedef struct
 \r
 //==========================================================================\r
 \r
+\r
+//from 16_pm\r
+//==========================================================================\r
+\r
+//     NOTE! PMPageSize must be an even divisor of EMSPageSize, and >= 1024\r
+#define        EMSPageSize             16384\r
+#define        EMSPageSizeSeg  (EMSPageSize >> 4)\r
+#define        EMSPageSizeKB   (EMSPageSize >> 10)\r
+#define        EMSFrameCount   4\r
+#define        PMPageSize              4096\r
+#define        PMPageSizeSeg   (PMPageSize >> 4)\r
+#define        PMPageSizeKB    (PMPageSize >> 10)\r
+#define        PMEMSSubPage    (EMSPageSize / PMPageSize)\r
+\r
+#define        PMMinMainMem    10                      // Min acceptable # of pages from main\r
+#define        PMMaxMainMem    100                     // Max number of pages in main memory\r
+\r
+#define        PMThrashThreshold       1       // Number of page thrashes before panic mode\r
+#define        PMUnThrashThreshold     5       // Number of non-thrashing frames before leaving panic mode\r
+\r
+typedef        enum\r
+               {\r
+                       pml_Unlocked,\r
+                       pml_Locked\r
+               } PMLockType;\r
+\r
+typedef        enum\r
+               {\r
+                       pmba_Unused = 0,\r
+                       pmba_Used = 1,\r
+                       pmba_Allocated = 2\r
+               } PMBlockAttr;\r
+\r
+typedef        struct\r
+               {\r
+                       dword   offset;         // Offset of chunk into file\r
+                       word            length;         // Length of the chunk\r
+\r
+                       int                     xmsPage;        // If in XMS, (xmsPage * PMPageSize) gives offset into XMS handle\r
+\r
+                       PMLockType      locked;         // If set, this page can't be purged\r
+                       int                     emsPage;        // If in EMS, logical page/offset into page\r
+                       int                     mainPage;       // If in Main, index into handle array\r
+\r
+                       dword   lastHit;        // Last frame number of hit\r
+               } PageListStruct;\r
+\r
+typedef        struct\r
+               {\r
+                       int                     baseEMSPage;    // Base EMS page for this phys frame\r
+                       dword   lastHit;                // Last frame number of hit\r
+               } EMSListStruct;\r
+\r
+//     Main Mem specific variables\r
+typedef struct\r
+{\r
+       boolean                 MainPresent;\r
+       memptr                  MainMemPages[PMMaxMainMem];\r
+       PMBlockAttr             MainMemUsed[PMMaxMainMem];\r
+       int                             MainPagesAvail;\r
+} pm_mmi_t;\r
+\r
+//     EMS specific variables\r
+typedef struct\r
+{\r
+       boolean                 EMSPresent;\r
+       unsigned int                    EMSVer;\r
+       word                    EMSAvail,EMSPagesAvail,EMSHandle,\r
+                                       EMSPageFrame,EMSPhysicalPage;\r
+       word                    totalEMSpages, freeEMSpages, EMSpagesmapped;\r
+       EMSListStruct   EMSList[EMSFrameCount];\r
+} pm_emmi_t;\r
+\r
+//     XMS specific variables\r
+typedef struct\r
+{\r
+       boolean                 XMSPresent;\r
+       word                    XMSAvail,XMSPagesAvail,XMSHandle;//,XMSVer;\r
+       dword                   XMSDriver;\r
+       int                             XMSProtectPage;// = -1;\r
+} pm_xmmi_t;\r
+\r
+//     File specific variables\r
+typedef struct\r
+{\r
+       char                    PageFileName[13];// = {"VSWAP."};\r
+       int                             PageFile;// = -1;\r
+       word                    ChunksInFile;\r
+       word                    PMSpriteStart,PMSoundStart;\r
+} pm_fi_t;\r
+\r
+//     General usage variables\r
+typedef struct\r
+{\r
+       boolean                 PMStarted,\r
+                                       PMPanicMode,\r
+                                       PMThrashing;\r
+       word                    XMSPagesUsed,\r
+                                       EMSPagesUsed,\r
+                                       MainPagesUsed,\r
+                                       PMNumBlocks;\r
+       long                    PMFrameCount;\r
+       PageListStruct  far *PMPages;\r
+       __SEGA *PMSegPages;\r
+       pm_mmi_t        mm;\r
+       pm_emmi_t       emm;\r
+       pm_xmmi_t       xmm;\r
+       pm_fi_t fi;\r
+} pm_t;\r
+\r
+//==========================================================================\r
+\r
 //from 16_ca\r
 //==========================================================================\r
 \r
@@ -209,9 +321,9 @@ typedef struct
        byte            ca_levelbit,ca_levelnum;\r
        ca_handle_t     file;           //files to open\r
        ca_mapinfo_t    camap;\r
-       //_seg  *grsegs[NUMCHUNKS];\r
-       //byte          far     grneeded[NUMCHUNKS];\r
-       //huffnode huffnode;\r
+       __SEGA  *grsegs[NUMCHUNKS];\r
+       byte            far     grneeded[NUMCHUNKS];\r
+       huffnode huffnode;\r
 } ca_t;\r
 \r
 //==========================================================================\r
@@ -221,6 +333,7 @@ typedef struct
 {\r
        video_t video;  // video settings variable\r
        ca_t            ca;     // ca stuff\r
+       pm_t            pm;     // pm stuff\r
        byte *pee;              // message for fps\r
        loghandle_t handle;     //handles for file logging\r
        kurokku_t kurokku;      //clock struct\r
index 9d0e7b3b5a8c1540b35d94ac2d12b0ef288666be..884aaea956fa090d1e9920804b0a8629388e696b 100755 (executable)
@@ -57,4 +57,7 @@ typedef void _seg * memptr;
 #define __SEGA _seg\r
 #endif\r
 \r
+#define _argv __argv\r
+#define _argc __argc\r
+\r
 #endif/*_TYPE_H_*/\r
index 1781754f0c0e00c6f1f973e2578b0b71234208ab..7464a32fae6bed8feee46c2d1f685da236d9b64b 100755 (executable)
-/* This file implements rudimentary XMS memory handling.
- * Documentation on the XMS API was found on http://www.qzx.com/pc-gpe/xms30.txt
- */
-
-#include "src\lib\xms.h"
-
-/* Set up the XMS driver, returns 0 on success and non-zero on failure */
-static int initxms(void)
-{
-       char XMSStatus = 0;
-
-       if ( XMSControl == 0 )
-       {
-               __asm {
-               ; Is an XMS driver installed?
-                       mov ax,4300h
-                       int 2Fh
-                       mov [XMSStatus], al
-               }
-
-               if ( XMSStatus == 0x80 )
-               {
-                       __asm {
-                       ; Get the address of the driver control function
-                               mov ax,4310h
-                               int 2Fh
-                               mov word ptr [XMSControl]  ,bx
-                               mov word ptr [XMSControl+2],es
-                       }
-               }
-       }
-
-       return ( XMSControl == 0 );
-}
-
-/* Allocate a slab of memory from XMS */
-void huge * xmsmalloc(long unsigned int size)
-{
-       unsigned int kB;
-       unsigned int XMSStatus = 0;
-       unsigned int XMSHandle = 0;
-       void huge * XMSPointer = NULL;
-       int n;
-
-       /* If we can not initialize XMS, the allocation fails */
-       if ( initxms() )
-               return NULL;
-
-       /* It is not possible to allocate more kilobytes than a 16-bit register can hold :-) */
-       if ( size / 1024 > UINT_MAX )
-               return NULL;
-
-       /* Get the next free entry in the handle <-> pointer mapping */
-       for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ )
-       {
-               if ( allocMapXMS[n].XMSPointer == NULL )
-                       break;
-       }
-
-       if ( n == MAX_XMS_ALLOCATIONS )
-               return NULL;
-
-       kB = size / 1024 + (size % 1024 > 0);
-
-       __asm {
-       ; Allocate [kB] kilobytes of XMS memory
-               mov ah, 09h
-               mov dx, [kB]
-               call [XMSControl]
-               mov [XMSStatus], ax
-               mov [XMSHandle], dx
-       }
-
-       /* Check if XMS allocation failed */
-       if ( XMSStatus == 0)
-               return NULL;
-
-       __asm {
-       ; Convert XMS handle to normal pointer
-               mov ah, 0Ch
-               mov dx, [XMSHandle]
-               call [XMSControl]
-               mov [XMSStatus], ax
-
-               mov word ptr [XMSPointer],  bx
-               mov word ptr [XMSPointer+2],dx
-       }
-
-       if ( XMSStatus == 0 )
-       {
-               /* Lock failed, deallocate the handle */
-               __asm {
-               ; Free XMS handle
-                       mov ah, 0Ah
-                       mov dx, [XMSHandle]
-                       call [XMSControl]
-
-               ; Return value is not really interesting 
-               ;   mov [XMSStatus], ax
-               }
-               return NULL;
-       }
-
-       /* Create an entry in the handle <-> pointer mapping */
-       allocMapXMS[n].XMSHandle = XMSHandle;
-       allocMapXMS[n].XMSPointer = XMSPointer;
-
-       return XMSPointer;
-}
-
-/* Free a pointer allocated with xmsalloc */
-void xmsfree(void huge * XMSPointer)
-{
-       int n;
-
-       if ( XMSPointer == NULL )
-               return;
-
-       if ( initxms() )
-               return;
-
-       for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ )
-       {
-               if ( allocMapXMS[n].XMSPointer == XMSPointer )
-               {
-                       int XMSHandle = allocMapXMS[n].XMSHandle;
-
-                       __asm {
-                       ; Unlock handle so we can free the memory block
-                               mov ah, 0Dh
-                               mov dx, [XMSHandle]
-                               call [XMSControl]
-
-                       ; Free XMS memory
-                               mov ah, 0Ah
-                               mov dx, [XMSHandle]
-                               call [XMSControl]
-
-                       ; Return value ignored
-                       }
-
-                       /* Clear handle <-> pointer map entry so it can be reused */
-                       allocMapXMS[n].XMSHandle = 0;
-                       allocMapXMS[n].XMSPointer = NULL;
-
-                       return;
-               }
-       }
-}
-
-/* Write a memory report for debugging purposes */
-void xmsreport(void/*FILE * stream*/)
-{
-       int XMSVersionNumber = 0;
-       unsigned int XMSLargestBlock = 0;
-       unsigned int XMSTotal = 0;
-
-       if ( initxms() )
-       {
-               puts("Could not initialize XMS Driver!");
-               return;
-       }
-
-       __asm {
-       ; Get the driver version number
-               mov ah,00h
-               call [XMSControl] ; Get XMS Version Number
-               mov [XMSVersionNumber], ax
-
-       ; Get the amount of free XMS memory
-               mov ah, 08h
-               call [XMSControl]
-               mov [XMSLargestBlock], ax
-               mov [XMSTotal], dx
-       }
-
-       //fprintf(stream, "XMS Version number: %d\n", XMSVersionNumber);
-       //fprintf(stream, "Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal);
-       printf("XMS Version number: %d\n", XMSVersionNumber);
-       printf("Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal);
-}
-
-/*int main()
-{
-       xmsreport(fopen("xms.log", "w"));
-       return 0;
-}*/
+/* This file implements rudimentary XMS memory handling.\r
+ * Documentation on the XMS API was found on http://www.qzx.com/pc-gpe/xms30.txt\r
+ */\r
+\r
+#include "src\lib\xms.h"\r
+\r
+/* Set up the XMS driver, returns 0 on success and non-zero on failure */\r
+static int initxms(void)\r
+{\r
+       char XMSStatus = 0;\r
+\r
+       if ( XMSControl == 0 )\r
+       {\r
+               __asm {\r
+               ; Is an XMS driver installed?\r
+                       mov ax,4300h\r
+                       int 2Fh\r
+                       mov [XMSStatus], al\r
+               }\r
+\r
+               if ( XMSStatus == 0x80 )\r
+               {\r
+                       __asm {\r
+                       ; Get the address of the driver control function\r
+                               mov ax,4310h\r
+                               int 2Fh\r
+                               mov word ptr [XMSControl]  ,bx\r
+                               mov word ptr [XMSControl+2],es\r
+                       }\r
+               }\r
+       }\r
+\r
+       return ( XMSControl == 0 );\r
+}\r
+\r
+/* Allocate a slab of memory from XMS */\r
+void huge * xmsmalloc(long unsigned int size)\r
+{\r
+       unsigned int kB;\r
+       unsigned int XMSStatus = 0;\r
+       unsigned int XMSHandle = 0;\r
+       void huge * XMSPointer = NULL;\r
+       int n;\r
+\r
+       /* If we can not initialize XMS, the allocation fails */\r
+       if ( initxms() )\r
+               return NULL;\r
+\r
+       /* It is not possible to allocate more kilobytes than a 16-bit register can hold :-) */\r
+       if ( size / 1024 > UINT_MAX )\r
+               return NULL;\r
+\r
+       /* Get the next free entry in the handle <-> pointer mapping */\r
+       for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ )\r
+       {\r
+               if ( allocMapXMS[n].XMSPointer == NULL )\r
+                       break;\r
+       }\r
+\r
+       if ( n == MAX_XMS_ALLOCATIONS )\r
+               return NULL;\r
+\r
+       kB = size / 1024 + (size % 1024 > 0);\r
+\r
+       __asm {\r
+       ; Allocate [kB] kilobytes of XMS memory\r
+               mov ah, 09h\r
+               mov dx, [kB]\r
+               call [XMSControl]\r
+               mov [XMSStatus], ax\r
+               mov [XMSHandle], dx\r
+       }\r
+\r
+       /* Check if XMS allocation failed */\r
+       if ( XMSStatus == 0)\r
+               return NULL;\r
+\r
+       __asm {\r
+       ; Convert XMS handle to normal pointer\r
+               mov ah, 0Ch\r
+               mov dx, [XMSHandle]\r
+               call [XMSControl]\r
+               mov [XMSStatus], ax\r
+\r
+               mov word ptr [XMSPointer],  bx\r
+               mov word ptr [XMSPointer+2],dx\r
+       }\r
+\r
+       if ( XMSStatus == 0 )\r
+       {\r
+               /* Lock failed, deallocate the handle */\r
+               __asm {\r
+               ; Free XMS handle\r
+                       mov ah, 0Ah\r
+                       mov dx, [XMSHandle]\r
+                       call [XMSControl]\r
+\r
+               ; Return value is not really interesting \r
+               ;   mov [XMSStatus], ax\r
+               }\r
+               return NULL;\r
+       }\r
+\r
+       /* Create an entry in the handle <-> pointer mapping */\r
+       allocMapXMS[n].XMSHandle = XMSHandle;\r
+       allocMapXMS[n].XMSPointer = XMSPointer;\r
+\r
+       return XMSPointer;\r
+}\r
+\r
+/* Free a pointer allocated with xmsalloc */\r
+void xmsfree(void huge * XMSPointer)\r
+{\r
+       int n;\r
+\r
+       if ( XMSPointer == NULL )\r
+               return;\r
+\r
+       if ( initxms() )\r
+               return;\r
+\r
+       for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ )\r
+       {\r
+               if ( allocMapXMS[n].XMSPointer == XMSPointer )\r
+               {\r
+                       int XMSHandle = allocMapXMS[n].XMSHandle;\r
+\r
+                       __asm {\r
+                       ; Unlock handle so we can free the memory block\r
+                               mov ah, 0Dh\r
+                               mov dx, [XMSHandle]\r
+                               call [XMSControl]\r
+\r
+                       ; Free XMS memory\r
+                               mov ah, 0Ah\r
+                               mov dx, [XMSHandle]\r
+                               call [XMSControl]\r
+\r
+                       ; Return value ignored\r
+                       }\r
+\r
+                       /* Clear handle <-> pointer map entry so it can be reused */\r
+                       allocMapXMS[n].XMSHandle = 0;\r
+                       allocMapXMS[n].XMSPointer = NULL;\r
+\r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+/* Write a memory report for debugging purposes */\r
+void xmsreport(void/*FILE * stream*/)\r
+{\r
+       int XMSVersionNumber = 0;\r
+       unsigned int XMSLargestBlock = 0;\r
+       unsigned int XMSTotal = 0;\r
+\r
+       if ( initxms() )\r
+       {\r
+               puts("Could not initialize XMS Driver!");\r
+               return;\r
+       }\r
+\r
+       __asm {\r
+       ; Get the driver version number\r
+               mov ah,00h\r
+               call [XMSControl] ; Get XMS Version Number\r
+               mov [XMSVersionNumber], ax\r
+\r
+       ; Get the amount of free XMS memory\r
+               mov ah, 08h\r
+               call [XMSControl]\r
+               mov [XMSLargestBlock], ax\r
+               mov [XMSTotal], dx\r
+       }\r
+\r
+       //fprintf(stream, "XMS Version number: %d\n", XMSVersionNumber);\r
+       //fprintf(stream, "Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal);\r
+       printf("XMS Version number: %d\n", XMSVersionNumber);\r
+       printf("Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal);\r
+}\r
+\r
+/*int main()\r
+{\r
+       xmsreport(fopen("xms.log", "w"));\r
+       return 0;\r
+}*/\r
index b65874943985849cfb9c69de61cff85f09136792..b1bdb012ae40ed897599a2ea46390e9449cc4708 100755 (executable)
@@ -1,28 +1,28 @@
-#ifndef _XMS_H_
-#define _XMS_H_
-#include <stddef.h> /* Definition of NULL */
-#include <limits.h> /* Definition of UINT_MAX */
-#include <stdio.h>  /* fprintf and (FILE *) */
-
-/* Allow external configuration of maximum concurrent XMS allocations */
-#ifndef MAX_XMS_ALLOCATIONS
-#define MAX_XMS_ALLOCATIONS 4
-#endif
-
-/* Address of the XMS driver */
-static long XMSControl;
-
-/* Mapping of XMS handle <-> normal pointer */
-typedef struct {
-       unsigned int XMSHandle;
-       void huge * XMSPointer;
-} XMSHandleMap;
-
-static XMSHandleMap allocMapXMS[MAX_XMS_ALLOCATIONS];
-
-static int initxms(void);
-void huge * xmsmalloc(long unsigned int size);
-void xmsfree(void huge * XMSPointer);
-void xmsreport(void/*FILE * stream*/);
-
-#endif/*_XMS_H_*/
+#ifndef _XMS_H_\r
+#define _XMS_H_\r
+#include <stddef.h> /* Definition of NULL */\r
+#include <limits.h> /* Definition of UINT_MAX */\r
+#include <stdio.h>  /* fprintf and (FILE *) */\r
+\r
+/* Allow external configuration of maximum concurrent XMS allocations */\r
+#ifndef MAX_XMS_ALLOCATIONS\r
+#define MAX_XMS_ALLOCATIONS 4\r
+#endif\r
+\r
+/* Address of the XMS driver */\r
+static long XMSControl;\r
+\r
+/* Mapping of XMS handle <-> normal pointer */\r
+typedef struct {\r
+       unsigned int XMSHandle;\r
+       void huge * XMSPointer;\r
+} XMSHandleMap;\r
+\r
+static XMSHandleMap allocMapXMS[MAX_XMS_ALLOCATIONS];\r
+\r
+static int initxms(void);\r
+void huge * xmsmalloc(long unsigned int size);\r
+void xmsfree(void huge * XMSPointer);\r
+void xmsreport(void/*FILE * stream*/);\r
+\r
+#endif/*_XMS_H_*/\r
diff --git a/src/lib/zcroll16.c b/src/lib/zcroll16.c
new file mode 100755 (executable)
index 0000000..12a5ee1
--- /dev/null
@@ -0,0 +1,360 @@
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+/*\r
+       scroll16 library~\r
+*/\r
+#include "src/lib/zcroll16.h"\r
+\r
+boolean boundary_check(int x, int y, int dx, int dy, int h, int w){\r
+       return (dx > 0 && (x + dx) < w) || (dx < 0 && (x + dx) >= 0) || (dy > 0 && (y + dy) < h) || (dy < 0 && (y + dy) >= 0) || (dx == dy && dx == 0);\r
+}\r
+\r
+boolean coll_check(int x, int y, int dx, int dy, map_view_t *map_v){\r
+       // Assume everything crosses at most 1 tile at once\r
+       return dx && crossable_tile(x + dx, map_v) || dy && crossable_tile(y + dy, map_v);\r
+}\r
+\r
+boolean walk(entity_t *ent, map_view_t *map_v)\r
+{\r
+       int dx = 1;\r
+       int dy = 1;\r
+       switch(ent->d)\r
+       {\r
+               case STOP:\r
+                       return;\r
+               case LEFT:\r
+                       dx = -dx;\r
+               case RIGHT:\r
+                       dy = 0;\r
+                       break;\r
+               case UP:\r
+                       dy = -dy;\r
+               case DOWN:\r
+                       dx = 0;\r
+                       break;\r
+       }\r
+       if(coll_check(ent->x, ent->y, dx, dy,  map_v)){\r
+               // Allow movement\r
+               // Set speed\r
+               // Start animation\r
+               // Mark next tile as occupied\r
+               // Mark this tile as vacant\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+void player_walk(player_t *player, map_view_t *map_v){\r
+       if(walk(player->ent, map_v) && boundary_check(map_v->tx, map_v->ty, dx, dy, map_v->map->width - 2*map_v->page->tilesw, map_v->map->height - 2*map_v->page->tilesh)){\r
+               mapScroll(map_v, player);\r
+               // (Un)load stuff?\r
+       }\r
+}\r
+\r
+\r
+void near mapScroll(map_view_t *mv, player_t *player){\r
+       word x, y;  /* coordinate for drawing */\r
+       int c = 1;\r
+       int delta;\r
+       mv->delta += player->dx | player->dy;\r
+       delta = mv->delta;\r
+       mv->d = (player->dx) ? (player->dx > 0) ? RIGHT : LEFT : (player->dy) ? (player->dy > 0) ? DOWN : UP : STOP;\r
+       switch(mv->d){\r
+               case DOWN:\r
+                       c = -1;\r
+                       delta = -delta;\r
+               case UP:\r
+                       if(!(delta + mv->dxThresh)){\r
+                               mv->delta = 0;\r
+                               mv->ty += c;\r
+                       }\r
+                       break;\r
+               case RIGHT:\r
+                       c = -1;\r
+                       delta = -delta;\r
+               case LEFT:\r
+                       if(!(delta + mv->dyThresh)){\r
+                               mv->delta = 0;\r
+                               mv->tx += c;\r
+                       }\r
+                       break;\r
+               default:\r
+                       break;\r
+       }\r
+\r
+       mv->video->r=1;\r
+}\r
+\r
+sword chkmap(map_t *map, word q)\r
+{\r
+//     bitmap_t bp;\r
+       static byte x[(MAPW*MAPH)+1] =\r
+{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 };\r
+/*1,   2,      3,      4,      0,      3,      3,      3,      3,      3,      3,      3,      3,      4,      1,      1,      1,      1,      1,      1,      \\r
+5,     6,      7,      8,      0,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+9,     10,     11,     12,     4,      1,      0,      1,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+13,    14,     15,     16,     0,      1,      1,      1,      5,      8,      1,      11,     11,     1,      1,      1,      1,      1,      1,      1,      \\r
+0,     0,      4,      0,      0,      0,      0,      0,      8,      8,      1,      11,     11,     3,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      0,      0,      0,      0,      8,      8,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      0,      0,      0,      0,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      \\r
+1,     1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      3,      3,      3,      3,      1,      2,      3,      4 };*/\r
+       //check for failed to load map\r
+       if((map->width == map->height == 0) && (q>0))\r
+       {\r
+               //initiate a null map!\r
+               map->width=MAPW;///2;\r
+               map->height=MAPH;///2;\r
+//             map->data = malloc(((map->width*map->height)+1)*sizeof(byte));\r
+               map->data = &x;\r
+               map->tiles = malloc(sizeof(tiles_t));\r
+               //fix this to be far~\r
+//             bp = bitmapLoadPcx("data/ed.pcx");\r
+//             map->tiles->data = &bp;\r
+               map->tiles->debug_data = map->data;\r
+               map->tiles->tileHeight = 16;\r
+               map->tiles->tileWidth = 16;\r
+               map->tiles->rows = 1;\r
+               map->tiles->cols = 1;\r
+               map->tiles->debug_text = true;\r
+       }\r
+       else map->tiles->debug_text = false;\r
+       return 0;\r
+}\r
+\r
+//TODO: player position here\r
+void mapGoTo(map_view_t *mv, int tx, int ty)\r
+{\r
+       int px, py;\r
+       unsigned int i;\r
+\r
+       /* set up the coordinates */\r
+       mv->tx = tx;\r
+       mv->ty = ty;\r
+       mv->page->delta = 0;\r
+\r
+       /* set up the thresholds */\r
+       mv->dxThresh = mv->map->tiles[0]->tileWidth * 2;\r
+       mv->dyThresh = mv->map->tiles[0]->tileHeight * 2;\r
+\r
+       /* draw the tiles */\r
+       modexClearRegion(mv->page, 0, 0, mv->page->width, mv->page->height, 0);\r
+       py=0;\r
+       i=mv->ty * mv->map->width + mv->tx;\r
+/*     for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) {\r
+               mapDrawWRow(&mv[0], tx-1, ty, py);\r
+       i+=mv->map->width - tx;\r
+       }\r
+       if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height);\r
+//     {\r
+//             unsigned int k,j,o;\r
+//             // fill screen with a distinctive pattern \r
+//             for (k=0;k < vga_state.vga_width;k++) {\r
+//                     o = k >> 2;\r
+//                     vga_write_sequencer(0x02/*map mask*//*,1 << (k&3));\r
+//                             for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride)\r
+//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!\r
+//             }\r
+//     }\r
+       modexCopyPageRegion(mv[3].page, mv[0].page, 0, 0, 0, 0, 24, 32);*/\r
+}\r
+\r
+void near\r
+mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y)\r
+{\r
+       word rx;\r
+       word ry;\r
+       word textx=0;\r
+       word texty=0;\r
+       //if(i==0) i=2;\r
+       if(i==0)\r
+       {\r
+               //wwww\r
+               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color!\r
+       }\r
+       else\r
+       {\r
+               rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth);\r
+               ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight);\r
+////0000printf("i=%d\n", i);\r
+               switch(t->debug_text)\r
+               {\r
+                       case 0:\r
+#ifndef TILERENDER\r
+                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1));\r
+                               //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i]));\r
+#else\r
+                               PBUFBFUN                (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));\r
+                               /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */\r
+                               //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));\r
+                               //modexDrawBmpRegion    (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data));\r
+#endif\r
+                       break;\r
+                       case 1:\r
+                               modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1);\r
+                               //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data));\r
+                               /*for(texty=0; texty<2; texty++)\r
+                               {\r
+                                       for(textx=0; textx<2; textx++)\r
+                                       {*/\r
+//                                             modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data));\r
+/*                                     }\r
+                               }*/\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+unsigned char shinku_fps_indicator_page = 2;\r
+boolean pageflipflop = 1;\r
+boolean pageploop = 1;\r
+\r
+/*     sync    */\r
+void shinku(global_game_variables_t *gv)\r
+{\r
+       word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen\r
+       word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen\r
+       word w = 64, h = 8, col = 7, bgcol = 0, type = 1;\r
+       byte o,o2,i;\r
+       if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second))\r
+       {\r
+               sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv));\r
+               //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45);\r
+               modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee);\r
+               gv->kurokku.tiku=0;\r
+       }else //copy dat sheet\r
+       gv->kurokku.tiku++;\r
+\r
+       switch(gv->kurokku.fpscap)\r
+       {\r
+               case 0:\r
+                       gv->kurokku.frames_per_second=1;\r
+               break;\r
+               case 1:\r
+                       //turn this off if XT\r
+                       vga_wait_for_vsync();\r
+                       gv->kurokku.frames_per_second=60;\r
+               break;\r
+       }\r
+       if(pageflipflop){\r
+       if(gv->video.r){\r
+               if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height);\r
+               modexShowPage(&(gv->video.page[gv->video.p]));\r
+               if(!pageploop) gv->video.p=!gv->video.p;\r
+               gv->video.r=!gv->video.r;\r
+       }\r
+       }\r
+}\r
+\r
+void near animatePlayer(map_view_t *pip, player_t *player,  sword scrollswitch)\r
+{\r
+       sword x = player->x;\r
+       sword y = player->y;\r
+       sword bx = x+16;        //buffer's x\r
+       sword by = y+16;        //buffer's y\r
+       word dire=32; //direction\r
+       sword qq; //scroll offset\r
+       word ls = player->persist_aniframe;\r
+\r
+       switch(scrollswitch)\r
+       {\r
+               case 0:\r
+                       qq = 0;\r
+               break;\r
+               default:\r
+                       qq = ((player->q)*(player->speed));\r
+               break;\r
+       }\r
+       //x-=4;\r
+       y-=pip->map->tiles->tileHeight;\r
+       switch (player->d)\r
+       {\r
+               case 0:\r
+                       //up\r
+                       dire*=player->d;\r
+                       y-=qq;\r
+                       by-=4;\r
+               break;\r
+               case 3:\r
+                       // right\r
+                       dire*=(player->d-2);\r
+                       x+=qq;\r
+                       bx+=4;\r
+               break;\r
+               case 2:\r
+               break;\r
+               case 4:\r
+                       //down\r
+                       dire*=(player->d-2);\r
+                       y+=qq;\r
+                       by+=4;\r
+               break;\r
+               case 1:\r
+                       //left\r
+                       dire*=(player->d+2);\r
+                       x-=qq;\r
+                       bx-=4;\r
+               break;\r
+       }\r
+\r
+#ifdef SPRITE\r
+#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 48, dire, 24, 32,        PLAYERBMPDATA);\r
+#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32,        PLAYERBMPDATA);\r
+#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 24, 32, PLAYERBMPDATA);\r
+#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32,        PLAYERBMPDATA);\r
+#else\r
+#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 2+dire);\r
+#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire);\r
+#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, dire);\r
+#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire);\r
+#endif\r
+       if(!pageflipflop)\r
+               modexCopyPageRegion(pip->page, pip->page, x-4, y-4, x-4, y-4, 28, 36);\r
+       else{\r
+               //copy old bg to page0\r
+               //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0,   20, 36);\r
+               //update buffer\r
+               //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0,   x, y,   20, 36);\r
+       }\r
+       switch(ls)\r
+       {\r
+               case 1:\r
+                       FRAME1\r
+               break;\r
+               case 2:\r
+                       FRAME2\r
+               break;\r
+               case 3:\r
+                       FRAME3\r
+               break;\r
+               case 4:\r
+                       FRAME4\r
+               break;\r
+       }\r
+       pip->video->r=1;\r
+}\r
diff --git a/src/lib/zcroll16.h b/src/lib/zcroll16.h
new file mode 100755 (executable)
index 0000000..6f66342
--- /dev/null
@@ -0,0 +1,116 @@
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#ifndef __ZCROLL16_H_\r
+#define __ZCROLL16_H_\r
+\r
+#include "src/lib/16_head.h"\r
+//#include "src/lib/bakapee.h"\r
+#include "src/lib/modex16.h"\r
+//#include "src/lib/16_in.h"\r
+#include "src/lib/bitmap.h"\r
+#include "src/lib/16_map.h" //map is loaded here www\r
+#include "src/lib/16_timer.h"\r
+#include "src/lib/wcpu/wcpu.h"\r
+\r
+#include <hw/cpu/cpu.h>\r
+#include <hw/dos/dos.h>\r
+#include <hw/vga/vga.h>\r
+#include <hw/vga/vrl.h>\r
+\r
+#define SPRITE\r
+//#define TILERENDER\r
+\r
+//modexDrawSpritePBufRegion\r
+//modexDrawBmpPBufRegion\r
+#define PBUFSFUN               modexDrawSpriteRegion\r
+#define PBUFBFUN               modexDrawBmpRegion\r
+#define PLAYERBMPDATA  player->data\r
+\r
+typedef struct {\r
+       map_t *map;\r
+       page_t *page;\r
+       int tx; //appears to be the top left tile position on the viewable screen map\r
+       int ty; //appears to be the top left tile position on the viewable screen map\r
+       word dxThresh; //Threshold for physical tile switch\r
+       word dyThresh; //Threshold for physical tile switch\r
+       video_t *video; //pointer to game variables of the video\r
+       pan_t *pan;             //pointer the the page panning debug system\r
+} map_view_t;\r
+\r
+#define MAPW   40\r
+#define MAPH   30\r
+\r
+enum direction {STOP, UP, DOWN, LEFT, RIGHT};\r
+typedef struct {\r
+       word id;        /* the Identification number of the page~ For layering~ */\r
+       byte far* data; /* the data for the page */\r
+       word sw;                /* screen width */\r
+       word sh;                /* screen heigth */\r
+       word tw;                /* screen width in tiles */\r
+       word th;                /* screen height in tiles */\r
+       word width;             /* virtual width of the page */\r
+       word height;    /* virtual height of the page */\r
+       word tilesw;            /* virtual screen width in tiles */\r
+       word tilesh;            /* virtual screen height in tiles */\r
+       sword tilemidposscreenx;        /* middle tile position */\r
+       sword tilemidposscreeny;        /* middle tile position */\r
+       sword tileplayerposscreenx;     /* player position on screen */\r
+       sword tileplayerposscreeny;     /* player position on screen */\r
+       word stridew;                   /*width/4*/\r
+       word pagesize;                  /* page size */\r
+       word pi;                                /* incremention page by this much to preserve location */\r
+       word delta;                     // How much should we shift the page for smooth scrolling\r
+       direction d;                    // Direction we should shift the page\r
+} page_t;\r
+extern boolean pageflipflop, pageploop;\r
+extern unsigned char shinku_fps_indicator_page;\r
+\r
+/* Map is presumed to:\r
+ * 1. Have all the required layers and tilesets within itself\r
+ * 2. Have a 'fence' around accessible blocks to simplify boundary logic\r
+ * 3. Have a persistent map and tile size among the layers\r
+ * Map view is presumed to:\r
+ * 1. Calculate, store and update a panning info, which includes, but not limited to:\r
+ *     combined layer information, actual map representation (reflecting real state of the game),\r
+ *     pixel shift for smooth tile scrolling.\r
+ * 2. Provide ways to draw a visible part of map. For simplicity with smooth scrolling, \r
+ *     additional row/column is always drawn at the each side of the map. This implies that 'fence'\r
+ *     should have a sprite too. Map is drawn left-to-right, top-to-bottom.\r
+ */\r
+\r
+// Move an entity around. Should actually be in 16_entity\r
+boolean walk(entity_t *ent, map_view_t *map_v);\r
+\r
+// Move player around and call map scrolling if required/possible\r
+void walk_player(player_t *player, map_view_t *map_v);\r
+\r
+// Scroll map in one direction (assumed from player's movement)\r
+void near mapScroll(map_view_t *mv, player_t *player);\r
+sword chkmap(map_t *map, word q);\r
+void mapGoTo(map_view_t *mv, int tx, int ty);\r
+void near mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y);\r
+//void qclean();\r
+void shinku(global_game_variables_t *gv);\r
+void near animatePlayer(map_view_t *pip, player_t *player, sword scrollswitch);\r
+\r
+#endif /*__ZCROLL16_H_*/\r
index e36a85320bd449fe97c6b881e4ff2c576e2fcd3c..04126d4eb1a860ffc6805f32db80f060f675de0d 100755 (executable)
-/* midi.c
- *
- * Adlib OPL2/OPL3 FM synthesizer chipset test program.
- * Play MIDI file using the OPLx synthesizer (well, poorly anyway)
- * (C) 2010-2012 Jonathan Campbell.
- * Hackipedia DOS library.
- *
- * This code is licensed under the LGPL.
- * <insert LGPL legal text here>
- *
- * Compiles for intended target environments:
- *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]
- */
-#include <stdio.h>
-#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <math.h>
-#include <dos.h>
-
-#include "src/lib/doslib/vga.h"
-#include "src/lib/doslib/dos.h"
-#include "src/lib/doslib/8254.h"               /* 8254 timer */
-#include "src/lib/doslib/8259.h"
-#include "src/lib/doslib/vgagui.h"
-#include "src/lib/doslib/vgatty.h"
-#include "src/lib/doslib/adlib.h"
-
-/* one per OPL channel */
-struct midi_note {
-       unsigned char           note_number;
-       unsigned char           note_velocity;
-       unsigned char           note_track;     /* from what MIDI track */
-       unsigned char           note_channel;   /* from what MIDI channel */
-       unsigned int            busy:1;         /* if occupied */
-};
-
-struct midi_channel {
-       unsigned char           program;
-};
-
-struct midi_track {
-       /* track data, raw */
-       unsigned char*          raw;            /* raw data base */
-       unsigned char*          fence;          /* raw data end (last byte + 1) */
-       unsigned char*          read;           /* raw data read ptr */
-       /* state */
-       unsigned long           us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */
-       unsigned long           us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */
-       unsigned long           wait;
-       unsigned char           last_status;    /* MIDI last status byte */
-       unsigned int            eof:1;          /* we hit the end of the track */
-};
-
-#define MIDI_MAX_CHANNELS      16
-#define MIDI_MAX_TRACKS                64
-
-struct midi_note               midi_notes[ADLIB_FM_VOICES];
-struct midi_channel            midi_ch[MIDI_MAX_CHANNELS];
-struct midi_track              midi_trk[MIDI_MAX_TRACKS];
-static unsigned int            midi_trk_count=0;
-static volatile unsigned char  midi_playing=0;
-
-/* MIDI params. Nobody ever said it was a straightforward standard!
- * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */
-static unsigned int ticks_per_quarter_note=0;  /* "Ticks per beat" */
-
-static void (interrupt *old_irq0)();
-static volatile unsigned long irq0_ticks=0;
-static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0;
-
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */
-       return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p));
-}
-#endif
-
-static inline unsigned char midi_trk_read(struct midi_track *t) {
-       unsigned char c;
-
-       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */
-       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) {
-               t->eof = 1;
-               return 0xFF;
-       }
-
-       c = *(t->read);
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-       if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */
-               t->read = MK_FP(FP_SEG(t->read)+0x1,0);
-       else
-               t->read++;
-#else
-       t->read++;
-#endif
-       return c;
-}
-
-void midi_trk_end(struct midi_track *t) {
-       t->wait = ~0UL;
-       t->read = t->fence;
-}
-
-void midi_trk_skip(struct midi_track *t,unsigned long len) {
-       unsigned long rem;
-
-       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */
-       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence)
-               return;
-
-       if (len > 0xFFF0UL) {
-               midi_trk_end(t);
-               return;
-       }
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-       {
-               unsigned long tt;
-
-               tt = farptr2phys(t->read);
-               rem = farptr2phys(t->fence) - tt;
-               if (rem > len) rem = len;
-               tt += rem;
-               t->read = MK_FP(tt>>4,tt&0xF);
-       }
-#else
-       rem = (unsigned long)(t->fence - t->read);
-       if (len > rem) len = rem;
-       t->read += len;
-#endif
-}
-
-static const uint32_t midikeys_freqs[0x80] = {
-       0x00082d01,     /* key 0 = 8.17579891564371Hz */
-       0x0008a976,     /* key 1 = 8.66195721802725Hz */
-       0x00092d51,     /* key 2 = 9.17702399741899Hz */
-       0x0009b904,     /* key 3 = 9.72271824131503Hz */
-       0x000a4d05,     /* key 4 = 10.3008611535272Hz */
-       0x000ae9d3,     /* key 5 = 10.9133822322814Hz */
-       0x000b8ff4,     /* key 6 = 11.5623257097386Hz */
-       0x000c3ff6,     /* key 7 = 12.2498573744297Hz */
-       0x000cfa70,     /* key 8 = 12.9782717993733Hz */
-       0x000dc000,     /* key 9 = 13.75Hz */
-       0x000e914f,     /* key 10 = 14.5676175474403Hz */
-       0x000f6f11,     /* key 11 = 15.4338531642539Hz */
-       0x00105a02,     /* key 12 = 16.3515978312874Hz */
-       0x001152ec,     /* key 13 = 17.3239144360545Hz */
-       0x00125aa2,     /* key 14 = 18.354047994838Hz */
-       0x00137208,     /* key 15 = 19.4454364826301Hz */
-       0x00149a0a,     /* key 16 = 20.6017223070544Hz */
-       0x0015d3a6,     /* key 17 = 21.8267644645627Hz */
-       0x00171fe9,     /* key 18 = 23.1246514194771Hz */
-       0x00187fed,     /* key 19 = 24.4997147488593Hz */
-       0x0019f4e0,     /* key 20 = 25.9565435987466Hz */
-       0x001b8000,     /* key 21 = 27.5Hz */
-       0x001d229e,     /* key 22 = 29.1352350948806Hz */
-       0x001ede22,     /* key 23 = 30.8677063285078Hz */
-       0x0020b404,     /* key 24 = 32.7031956625748Hz */
-       0x0022a5d8,     /* key 25 = 34.647828872109Hz */
-       0x0024b545,     /* key 26 = 36.7080959896759Hz */
-       0x0026e410,     /* key 27 = 38.8908729652601Hz */
-       0x00293414,     /* key 28 = 41.2034446141087Hz */
-       0x002ba74d,     /* key 29 = 43.6535289291255Hz */
-       0x002e3fd2,     /* key 30 = 46.2493028389543Hz */
-       0x0030ffda,     /* key 31 = 48.9994294977187Hz */
-       0x0033e9c0,     /* key 32 = 51.9130871974931Hz */
-       0x00370000,     /* key 33 = 55Hz */
-       0x003a453d,     /* key 34 = 58.2704701897612Hz */
-       0x003dbc44,     /* key 35 = 61.7354126570155Hz */
-       0x00416809,     /* key 36 = 65.4063913251497Hz */
-       0x00454bb0,     /* key 37 = 69.295657744218Hz */
-       0x00496a8b,     /* key 38 = 73.4161919793519Hz */
-       0x004dc820,     /* key 39 = 77.7817459305202Hz */
-       0x00526829,     /* key 40 = 82.4068892282175Hz */
-       0x00574e9b,     /* key 41 = 87.307057858251Hz */
-       0x005c7fa4,     /* key 42 = 92.4986056779086Hz */
-       0x0061ffb5,     /* key 43 = 97.9988589954373Hz */
-       0x0067d380,     /* key 44 = 103.826174394986Hz */
-       0x006e0000,     /* key 45 = 110Hz */
-       0x00748a7b,     /* key 46 = 116.540940379522Hz */
-       0x007b7888,     /* key 47 = 123.470825314031Hz */
-       0x0082d012,     /* key 48 = 130.812782650299Hz */
-       0x008a9760,     /* key 49 = 138.591315488436Hz */
-       0x0092d517,     /* key 50 = 146.832383958704Hz */
-       0x009b9041,     /* key 51 = 155.56349186104Hz */
-       0x00a4d053,     /* key 52 = 164.813778456435Hz */
-       0x00ae9d36,     /* key 53 = 174.614115716502Hz */
-       0x00b8ff49,     /* key 54 = 184.997211355817Hz */
-       0x00c3ff6a,     /* key 55 = 195.997717990875Hz */
-       0x00cfa700,     /* key 56 = 207.652348789973Hz */
-       0x00dc0000,     /* key 57 = 220Hz */
-       0x00e914f6,     /* key 58 = 233.081880759045Hz */
-       0x00f6f110,     /* key 59 = 246.941650628062Hz */
-       0x0105a025,     /* key 60 = 261.625565300599Hz */
-       0x01152ec0,     /* key 61 = 277.182630976872Hz */
-       0x0125aa2e,     /* key 62 = 293.664767917408Hz */
-       0x01372082,     /* key 63 = 311.126983722081Hz */
-       0x0149a0a7,     /* key 64 = 329.62755691287Hz */
-       0x015d3a6d,     /* key 65 = 349.228231433004Hz */
-       0x0171fe92,     /* key 66 = 369.994422711634Hz */
-       0x0187fed4,     /* key 67 = 391.995435981749Hz */
-       0x019f4e00,     /* key 68 = 415.304697579945Hz */
-       0x01b80000,     /* key 69 = 440Hz */
-       0x01d229ec,     /* key 70 = 466.16376151809Hz */
-       0x01ede220,     /* key 71 = 493.883301256124Hz */
-       0x020b404a,     /* key 72 = 523.251130601197Hz */
-       0x022a5d81,     /* key 73 = 554.365261953744Hz */
-       0x024b545c,     /* key 74 = 587.329535834815Hz */
-       0x026e4104,     /* key 75 = 622.253967444162Hz */
-       0x0293414f,     /* key 76 = 659.25511382574Hz */
-       0x02ba74da,     /* key 77 = 698.456462866008Hz */
-       0x02e3fd24,     /* key 78 = 739.988845423269Hz */
-       0x030ffda9,     /* key 79 = 783.990871963499Hz */
-       0x033e9c01,     /* key 80 = 830.60939515989Hz */
-       0x03700000,     /* key 81 = 880Hz */
-       0x03a453d8,     /* key 82 = 932.32752303618Hz */
-       0x03dbc440,     /* key 83 = 987.766602512248Hz */
-       0x04168094,     /* key 84 = 1046.50226120239Hz */
-       0x0454bb03,     /* key 85 = 1108.73052390749Hz */
-       0x0496a8b8,     /* key 86 = 1174.65907166963Hz */
-       0x04dc8208,     /* key 87 = 1244.50793488832Hz */
-       0x0526829e,     /* key 88 = 1318.51022765148Hz */
-       0x0574e9b5,     /* key 89 = 1396.91292573202Hz */
-       0x05c7fa49,     /* key 90 = 1479.97769084654Hz */
-       0x061ffb53,     /* key 91 = 1567.981743927Hz */
-       0x067d3802,     /* key 92 = 1661.21879031978Hz */
-       0x06e00000,     /* key 93 = 1760Hz */
-       0x0748a7b1,     /* key 94 = 1864.65504607236Hz */
-       0x07b78880,     /* key 95 = 1975.5332050245Hz */
-       0x082d0128,     /* key 96 = 2093.00452240479Hz */
-       0x08a97607,     /* key 97 = 2217.46104781498Hz */
-       0x092d5171,     /* key 98 = 2349.31814333926Hz */
-       0x09b90410,     /* key 99 = 2489.01586977665Hz */
-       0x0a4d053c,     /* key 100 = 2637.02045530296Hz */
-       0x0ae9d36b,     /* key 101 = 2793.82585146403Hz */
-       0x0b8ff493,     /* key 102 = 2959.95538169308Hz */
-       0x0c3ff6a7,     /* key 103 = 3135.96348785399Hz */
-       0x0cfa7005,     /* key 104 = 3322.43758063956Hz */
-       0x0dc00000,     /* key 105 = 3520Hz */
-       0x0e914f62,     /* key 106 = 3729.31009214472Hz */
-       0x0f6f1100,     /* key 107 = 3951.06641004899Hz */
-       0x105a0250,     /* key 108 = 4186.00904480958Hz */
-       0x1152ec0e,     /* key 109 = 4434.92209562995Hz */
-       0x125aa2e3,     /* key 110 = 4698.63628667852Hz */
-       0x13720820,     /* key 111 = 4978.03173955329Hz */
-       0x149a0a79,     /* key 112 = 5274.04091060592Hz */
-       0x15d3a6d6,     /* key 113 = 5587.65170292806Hz */
-       0x171fe927,     /* key 114 = 5919.91076338615Hz */
-       0x187fed4e,     /* key 115 = 6271.92697570799Hz */
-       0x19f4e00a,     /* key 116 = 6644.87516127912Hz */
-       0x1b800000,     /* key 117 = 7040Hz */
-       0x1d229ec4,     /* key 118 = 7458.62018428944Hz */
-       0x1ede2200,     /* key 119 = 7902.13282009799Hz */
-       0x20b404a1,     /* key 120 = 8372.01808961916Hz */
-       0x22a5d81c,     /* key 121 = 8869.84419125991Hz */
-       0x24b545c7,     /* key 122 = 9397.27257335704Hz */
-       0x26e41040,     /* key 123 = 9956.06347910659Hz */
-       0x293414f2,     /* key 124 = 10548.0818212118Hz */
-       0x2ba74dac,     /* key 125 = 11175.3034058561Hz */
-       0x2e3fd24f,     /* key 126 = 11839.8215267723Hz */
-       0x30ffda9c      /* key 127 = 12543.853951416Hz */
-};
-
-static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) {
-       return midikeys_freqs[key&0x7F];
-}
-
-static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) {
-       unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */
-       unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */
-       unsigned int i,freen=~0;
-
-       for (i=0;i < ADLIB_FM_VOICES;i++) {
-               if (midi_notes[i].busy) {
-                       if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key)
-                               return &midi_notes[i];
-               }
-               else {
-                       if (freen == ~0) freen = i;
-               }
-       }
-
-       if (do_alloc && freen != ~0) return &midi_notes[freen];
-       return NULL;
-}
-
-static void drop_fm_note(struct midi_channel *ch,unsigned char key) {
-       unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */
-       unsigned int i;
-
-       for (i=0;i < ADLIB_FM_VOICES;i++) {
-               if (midi_notes[i].busy && midi_notes[i].note_channel == ach) {
-                       midi_notes[i].busy = 0;
-                       break;
-               }
-       }
-}
-
-static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {
-       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0);
-       uint32_t freq = midi_note_freq(ch,key);
-       unsigned int ach;
-
-       if (note == NULL) return;
-
-       note->busy = 1;
-       note->note_number = key;
-       note->note_velocity = vel;
-       note->note_track = (unsigned int)(t - midi_trk);
-       note->note_channel = (unsigned int)(ch - midi_ch);
-       ach = (unsigned int)(note - midi_notes); /* which FM channel? */
-       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);
-       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */
-       adlib_fm[ach].mod.sustain_level = vel >> 3;
-       adlib_fm[ach].mod.key_on = 1;
-       adlib_update_groupA0(ach,&adlib_fm[ach]);
-}
-
-static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {
-       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1);
-       uint32_t freq = midi_note_freq(ch,key);
-       unsigned int ach;
-
-       /* HACK: Ignore percussion */
-       if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ ||
-               (ch->program >= 112 && ch->program <= 119)/*Percussive*/ ||
-               ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/)
-               return;
-
-       if (note == NULL) {
-               /* then we'll have to knock one off to make room */
-               drop_fm_note(ch,key);
-               note = get_fm_note(t,ch,key,1);
-               if (note == NULL) return;
-       }
-
-       note->busy = 1;
-       note->note_number = key;
-       note->note_velocity = vel;
-       note->note_track = (unsigned int)(t - midi_trk);
-       note->note_channel = (unsigned int)(ch - midi_ch);
-       ach = (unsigned int)(note - midi_notes); /* which FM channel? */
-       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);
-       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */
-       adlib_fm[ach].mod.sustain_level = vel >> 3;
-       adlib_fm[ach].mod.key_on = 1;
-       adlib_update_groupA0(ach,&adlib_fm[ach]);
-}
-
-static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {
-       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0);
-       uint32_t freq = midi_note_freq(ch,key);
-       unsigned int ach;
-
-       if (note == NULL) return;
-
-       note->busy = 0;
-       ach = (unsigned int)(note - midi_notes); /* which FM channel? */
-       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);
-       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */
-       adlib_fm[ach].mod.sustain_level = vel >> 3;
-       adlib_fm[ach].mod.key_on = 0;
-       adlib_update_groupA0(ach,&adlib_fm[ach]);
-}
-
-static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) {
-}
-
-static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) {
-       ch->program = inst;
-}
-
-static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) {
-}
-
-static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) {
-}
-
-unsigned long midi_trk_read_delta(struct midi_track *t) {
-       unsigned long tc = 0;
-       unsigned char c = 0,b;
-
-       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */
-       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence)
-               return tc;
-
-       while (c < 4) {
-               b = midi_trk_read(t);
-               tc = (tc << 7UL) + (unsigned long)(b&0x7F);
-               if (!(b&0x80)) break;
-               c++;
-       }
-
-       return tc;
-}
-
-void midi_tick_track(unsigned int i) {
-       struct midi_track *t = midi_trk + i;
-       struct midi_channel *ch;
-       unsigned char b,c,d;
-       int cnt=0;
-
-       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */
-       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) {
-               t->eof = 1;
-               return;
-       }
-
-       t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note;
-       while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) {
-               t->us_tick_cnt_mtpq -= t->us_per_quarter_note;
-               cnt++;
-
-               while (t->wait == 0) {
-                       if ((unsigned long)t->read >= (unsigned long)t->fence) {
-                               t->eof = 1;
-                               break;
-                       }
-
-                       /* read pointer should be pointing at MIDI event bytes, just after the time delay */
-                       b = midi_trk_read(t);
-                       if (b&0x80) {
-                               if (b < 0xF8) {
-                                       if (b >= 0xF0)
-                                               t->last_status = 0;
-                                       else
-                                               t->last_status = b;
-                               }
-                               if (b != 0x00 && ((b&0xF8) != 0xF0))
-                                       c = midi_trk_read(t);
-                       }
-                       else {
-                               /* blegh. last status */
-                               c = b;
-                               b = t->last_status;
-                       }
-                       switch (b>>4) {
-                               case 0x8: { /* note off */
-                                       d = midi_trk_read(t);
-                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */
-                                       on_key_off(t,ch,c,d);
-                                       } break;
-                               case 0x9: { /* note on */
-                                       d = midi_trk_read(t);
-                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */
-                                       if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */
-                                       else on_key_off(t,ch,c,d);
-                                       } break;
-                               case 0xA: { /* polyphonic aftertouch */
-                                       d = midi_trk_read(t);
-                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */
-                                       on_key_aftertouch(t,ch,c,d);
-                                       } break;
-                               case 0xB: { /* control change */
-                                       d = midi_trk_read(t);
-                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */
-                                       on_control_change(t,ch,c,d);
-                                       } break;
-                               case 0xC: { /* program change */
-                                       on_program_change(t,ch,c); /* c=instrument d=not used */
-                                       } break;
-                               case 0xD: { /* channel aftertouch */
-                                       on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */
-                                       } break;
-                               case 0xE: { /* pitch bend */
-                                       d = midi_trk_read(t);
-                                       on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */
-                                       } break;
-                               case 0xF: { /* event */
-                                       if (b == 0xFF) {
-                                               if (c == 0x7F) { /* c=type d=len */
-                                                       unsigned long len = midi_trk_read_delta(t);
-//                                                     fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence);
-                                                       if (len < 512UL) {
-                                                               /* unknown */
-                                                               midi_trk_skip(t,len);
-                                                       }
-                                                       else {
-                                                               midi_trk_end(t);
-                                                       }
-                                               }
-                                               else if (c < 0x7F) {
-                                                       d = midi_trk_read(t);
-
-                                                       if (c == 0x51 && d >= 3) {
-                                                               d -= 3;
-                                                               t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+
-                                                                       ((unsigned long)midi_trk_read(t)<<8UL)+
-                                                                       ((unsigned long)midi_trk_read(t)<<0UL);
-
-                                                               if (1/*TODO: If format 0 or format 1*/) {
-                                                                       /* Ugh. Unless format 2, the tempo applies to all tracks */
-                                                                       int j;
-
-                                                                       for (j=0;j < midi_trk_count;j++) {
-                                                                               if (j != i) midi_trk[j].us_per_quarter_note =
-                                                                                       t->us_per_quarter_note;
-                                                                       }
-                                                               }
-                                                       }
-                                                       else {
-//                                                             fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence);
-                                                       }
-
-                                                       midi_trk_skip(t,d);
-                                               }
-                                               else {
-                                                       fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence);
-                                               }
-                                       }
-                                       else {
-                                               unsigned long len = midi_trk_read_delta(t);
-//                                             fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence);
-                                               midi_trk_skip(t,len);
-                                       }
-                                       } break;
-                               default:
-                                       if (b != 0x00) {
-                                               fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence);
-                                               midi_trk_end(t);
-                                       }
-                                       break;
-                       };
-
-                       /* and then read the next event */
-                       t->wait = midi_trk_read_delta(t);
-               }
-               if (t->wait != 0) {
-                       t->wait--;
-               }
-       }
-}
-
-void adlib_shut_up();
-void midi_reset_tracks();
-void midi_reset_channels();
-
-void midi_tick() {
-       if (midi_playing) {
-               unsigned int i;
-               int eof=0;
-
-               for (i=0;i < midi_trk_count;i++) {
-                       midi_tick_track(i);
-                       eof += midi_trk[i].eof?1:0;
-               }
-
-               if (eof >= midi_trk_count) {
-                       adlib_shut_up();
-                       midi_reset_tracks();
-                       midi_reset_channels();
-               }
-       }
-}
-
-/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */
-void interrupt irq0() {
-//     midi_tick();
-       irq0_ticks++;
-       if ((irq0_cnt += irq0_add) >= irq0_max) {
-               irq0_cnt -= irq0_max;
-               old_irq0();
-       }
-       else {
-               p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI);
-       }
-}
-
-void adlib_shut_up() {
-       int i;
-
-       memset(adlib_fm,0,sizeof(adlib_fm));
-       memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));
-       for (i=0;i < adlib_fm_voices;i++) {
-               struct adlib_fm_operator *f;
-               f = &adlib_fm[i].mod;
-               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
-               f = &adlib_fm[i].car;
-               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
-       }
-
-       for (i=0;i < adlib_fm_voices;i++) {
-               struct adlib_fm_operator *f;
-
-               midi_notes[i].busy = 0;
-               midi_notes[i].note_channel = 0;
-
-               f = &adlib_fm[i].mod;
-               f->mod_multiple = 1;
-               f->total_level = 63 - 16;
-               f->attack_rate = 15;
-               f->decay_rate = 4;
-               f->sustain_level = 0;
-               f->release_rate = 8;
-               f->f_number = 400;
-               f->sustain = 1;
-               f->octave = 4;
-               f->key_on = 0;
-
-               f = &adlib_fm[i].car;
-               f->mod_multiple = 1;
-               f->total_level = 63 - 16;
-               f->attack_rate = 15;
-               f->decay_rate = 4;
-               f->sustain_level = 0;
-               f->release_rate = 8;
-               f->f_number = 0;
-               f->sustain = 1;
-               f->octave = 0;
-               f->key_on = 0;
-       }
-
-       adlib_apply_all();
-}
-
-void midi_reset_track(unsigned int i) {
-       struct midi_track *t;
-
-       if (i >= MIDI_MAX_TRACKS) return;
-       t = &midi_trk[i];
-       t->eof = 0;
-       t->last_status = 0;
-       t->us_tick_cnt_mtpq = 0;
-       t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */
-       t->read = midi_trk[i].raw;
-       t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */
-}
-
-void midi_reset_tracks() {
-       int i;
-
-       for (i=0;i < midi_trk_count;i++)
-               midi_reset_track(i);
-}
-
-void midi_reset_channels() {
-       int i;
-
-       for (i=0;i < MIDI_MAX_CHANNELS;i++) {
-               midi_ch[i].program = 0;
-       }
-}
-
-int load_midi_file(const char *path) {
-       unsigned char tmp[256];
-       unsigned int tracks=0;
-       unsigned int tracki=0;
-       int fd;
-
-       fd = open(path,O_RDONLY|O_BINARY);
-       if (fd < 0) {
-               printf("Failed to load file %s\n",path);
-               return 0;
-       }
-
-       ticks_per_quarter_note = 0;
-       while (read(fd,tmp,8) == 8) {
-               uint32_t sz;
-
-               sz =    ((uint32_t)tmp[4] << (uint32_t)24) |
-                       ((uint32_t)tmp[5] << (uint32_t)16) |
-                       ((uint32_t)tmp[6] << (uint32_t)8) |
-                       ((uint32_t)tmp[7] << (uint32_t)0);
-               if (!memcmp(tmp,"MThd",4)) {
-                       unsigned short t,tdiv;
-
-                       if (sz < 6 || sz > 255) {
-                               fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz);
-                               goto err;
-                       }
-                       if (read(fd,tmp,(int)sz) != (int)sz) {
-                               fprintf(stderr,"MThd read error\n");
-                               goto err;
-                       }
-
-                       /* byte 0-1 = format type (0,1 or 2) */
-                       /* byte 2-3 = number of tracks */
-                       /* byte 4-5 = time divison */
-                       t = tmp[1] | (tmp[0] << 8);
-                       if (t > 1) {
-                               fprintf(stderr,"MThd type %u not supported\n",t);
-                               goto err; /* we only take type 0 or 1, don't support 2 */
-                       }
-                       tracks = tmp[3] | (tmp[2] << 8);
-                       if (tracks > MIDI_MAX_TRACKS) {
-                               fprintf(stderr,"MThd too many (%u) tracks\n",tracks);
-                               goto err;
-                       }
-                       tdiv = tmp[5] | (tmp[4] << 8);
-                       if (tdiv & 0x8000) {
-                               fprintf(stderr,"MThd SMPTE time division not supported\n");
-                               goto err; /* we do not support the SMPTE form */
-                       }
-                       if (tdiv == 0) {
-                               fprintf(stderr,"MThd time division == 0\n");
-                               goto err;
-                       }
-                       ticks_per_quarter_note = tdiv;
-               }
-               else if (!memcmp(tmp,"MTrk",4)) {
-                       if (sz == 0UL) continue;
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-                       if (sz > (640UL << 10UL)) goto err; /* 640KB */
-#elif TARGET_MSDOS == 32
-                       if (sz > (1UL << 20UL)) goto err; /* 1MB */
-#else
-                       if (sz > (60UL << 10UL)) goto err; /* 60KB */
-#endif
-                       if (tracki >= MIDI_MAX_TRACKS) goto err;
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-                       {
-                               unsigned segv;
-
-                               /* NTS: _fmalloc() is still limited to 64KB sizes */
-                               if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err;
-                               midi_trk[tracki].raw = MK_FP(segv,0);
-                       }
-#else
-                       midi_trk[tracki].raw = malloc(sz);
-#endif
-                       if (midi_trk[tracki].raw == NULL) goto err;
-                       midi_trk[tracki].read = midi_trk[tracki].raw;
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-                       {
-                               unsigned char far *p = midi_trk[tracki].raw;
-                               unsigned long rem = (unsigned long)sz;
-                               unsigned long cando;
-                               unsigned read;
-
-                               while (rem != 0UL) {
-                                       read = 0;
-
-                                       cando = 0x10000UL - (unsigned long)FP_OFF(p);
-                                       if (cando > rem) cando = rem;
-                                       if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */
-
-                                       if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err;
-                                       if (read != (unsigned)cando) goto err;
-
-                                       rem -= cando;
-                                       if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL)
-                                               p = MK_FP(FP_SEG(p)+0x1000,0);
-                                       else
-                                               p += (unsigned)cando;
-                               }
-
-                               cando = farptr2phys(p);
-                               midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF);
-                       }
-#else
-                       midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz;
-                       if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err;
-#endif
-                       tracki++;
-               }
-               else {
-                       fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]);
-                       goto err;
-               }
-       }
-       if (tracki == 0 || ticks_per_quarter_note == 0) goto err;
-       midi_trk_count = tracki;
-
-       fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note);
-
-       close(fd);
-       return 1;
-err:
-       close(fd);
-       return 0;
-}
-
-int main(int argc,char **argv) {
-       unsigned long ptick;
-       int i,c;
-
-       printf("ADLIB FM test program\n");
-       if (argc < 2) {
-               printf("You must specify a MIDI file to play\n");
-               return 1;
-       }
-
-       if (!probe_vga()) {
-               printf("Cannot init VGA\n");
-               return 1;
-       }
-       if (!init_adlib()) {
-               printf("Cannot init library\n");
-               return 1;
-       }
-       if (!probe_8254()) { /* we need the timer to keep time with the music */
-               printf("8254 timer not found\n");
-               return 1;
-       }
-
-       for (i=0;i < MIDI_MAX_TRACKS;i++) {
-               midi_trk[i].raw = NULL;
-               midi_trk[i].read = NULL;
-               midi_trk[i].fence = NULL;
-       }
-
-       if (load_midi_file(argv[1]) == 0) {
-               printf("Failed to load MIDI\n");
-               return 1;
-       }
-
-       write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); /* tick faster at 100Hz please */
-       irq0_cnt = 0;
-       irq0_add = 182;
-       irq0_max = 1000; /* about 18.2Hz */
-       old_irq0 = _dos_getvect(8);/*IRQ0*/
-       _dos_setvect(8,irq0);
-
-       adlib_shut_up();
-       midi_reset_channels();
-       midi_reset_tracks();
-       _cli();
-       irq0_ticks = ptick = 0;
-       _sti();
-       midi_playing = 1;
-
-       while (1) {
-               unsigned long adv;
-
-               _cli();
-               adv = irq0_ticks - ptick;
-               if (adv >= 100UL) adv = 100UL;
-               ptick = irq0_ticks;
-               _sti();
-
-               while (adv != 0) {
-                       midi_tick();
-                       adv--;
-               }
-
-               if (kbhit()) {
-                       c = getch();
-                       if (c == 0) c = getch() << 8;
-
-                       if (c == 27) {
-                               break;
-                       }
-               }
-       }
-
-       midi_playing = 0;
-       adlib_shut_up();
-       shutdown_adlib();
-       _dos_setvect(8,old_irq0);
-       write_8254_system_timer(0); /* back to normal 18.2Hz */
-
-       for (i=0;i < MIDI_MAX_TRACKS;i++) {
-               if (midi_trk[i].raw) {
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-                       _dos_freemem(FP_SEG(midi_trk[i].raw)); /* NTS: Because we allocated with _dos_allocmem */
-#else
-                       free(midi_trk[i].raw);
-#endif
-                       midi_trk[i].raw = NULL;
-               }
-               midi_trk[i].fence = NULL;
-               midi_trk[i].read = NULL;
-       }
-
-       return 0;
-}
+/* midi.c\r
+ *\r
+ * Adlib OPL2/OPL3 FM synthesizer chipset test program.\r
+ * Play MIDI file using the OPLx synthesizer (well, poorly anyway)\r
+ * (C) 2010-2012 Jonathan Campbell.\r
+ * Hackipedia DOS library.\r
+ *\r
+ * This code is licensed under the LGPL.\r
+ * <insert LGPL legal text here>\r
+ *\r
+ * Compiles for intended target environments:\r
+ *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]\r
+ */\r
\r
+#include <stdio.h>\r
+#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <malloc.h>\r
+#include <ctype.h>\r
+#include <fcntl.h>\r
+#include <math.h>\r
+#include <dos.h>\r
+\r
+#include "src/lib/doslib/vga.h"\r
+#include "src/lib/doslib/dos.h"\r
+#include "src/lib/doslib/8254.h"               /* 8254 timer */\r
+#include "src/lib/doslib/8259.h"\r
+#include "src/lib/doslib/vgagui.h"\r
+#include "src/lib/doslib/vgatty.h"\r
+#include "src/lib/doslib/adlib.h"\r
+\r
+/* one per OPL channel */\r
+struct midi_note {\r
+       unsigned char           note_number;\r
+       unsigned char           note_velocity;\r
+       unsigned char           note_track;     /* from what MIDI track */\r
+       unsigned char           note_channel;   /* from what MIDI channel */\r
+       unsigned int            busy:1;         /* if occupied */\r
+};\r
+\r
+struct midi_channel {\r
+       unsigned char           program;\r
+};\r
+\r
+struct midi_track {\r
+       /* track data, raw */\r
+       unsigned char*          raw;            /* raw data base */\r
+       unsigned char*          fence;          /* raw data end (last byte + 1) */\r
+       unsigned char*          read;           /* raw data read ptr */\r
+       /* state */\r
+       unsigned long           us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */\r
+       unsigned long           us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */\r
+       unsigned long           wait;\r
+       unsigned char           last_status;    /* MIDI last status byte */\r
+       unsigned int            eof:1;          /* we hit the end of the track */\r
+};\r
+\r
+#define MIDI_MAX_CHANNELS      16\r
+#define MIDI_MAX_TRACKS                64\r
+\r
+struct midi_note               midi_notes[ADLIB_FM_VOICES];\r
+struct midi_channel            midi_ch[MIDI_MAX_CHANNELS];\r
+struct midi_track              midi_trk[MIDI_MAX_TRACKS];\r
+static unsigned int            midi_trk_count=0;\r
+static volatile unsigned char  midi_playing=0;\r
+\r
+/* MIDI params. Nobody ever said it was a straightforward standard!\r
+ * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */\r
+static unsigned int ticks_per_quarter_note=0;  /* "Ticks per beat" */\r
+\r
+static void (interrupt *old_irq0)();\r
+static volatile unsigned long irq0_ticks=0;\r
+static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0;\r
+\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */\r
+       return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p));\r
+}\r
+#endif\r
+\r
+static inline unsigned char midi_trk_read(struct midi_track *t) {\r
+       unsigned char c;\r
+\r
+       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */\r
+       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) {\r
+               t->eof = 1;\r
+               return 0xFF;\r
+       }\r
+\r
+       c = *(t->read);\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+       if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */\r
+               t->read = MK_FP(FP_SEG(t->read)+0x1,0);\r
+       else\r
+               t->read++;\r
+#else\r
+       t->read++;\r
+#endif\r
+       return c;\r
+}\r
+\r
+void midi_trk_end(struct midi_track *t) {\r
+       t->wait = ~0UL;\r
+       t->read = t->fence;\r
+}\r
+\r
+void midi_trk_skip(struct midi_track *t,unsigned long len) {\r
+       unsigned long rem;\r
+\r
+       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */\r
+       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence)\r
+               return;\r
+\r
+       if (len > 0xFFF0UL) {\r
+               midi_trk_end(t);\r
+               return;\r
+       }\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+       {\r
+               unsigned long tt;\r
+\r
+               tt = farptr2phys(t->read);\r
+               rem = farptr2phys(t->fence) - tt;\r
+               if (rem > len) rem = len;\r
+               tt += rem;\r
+               t->read = MK_FP(tt>>4,tt&0xF);\r
+       }\r
+#else\r
+       rem = (unsigned long)(t->fence - t->read);\r
+       if (len > rem) len = rem;\r
+       t->read += len;\r
+#endif\r
+}\r
+\r
+static const uint32_t midikeys_freqs[0x80] = {\r
+       0x00082d01,     /* key 0 = 8.17579891564371Hz */\r
+       0x0008a976,     /* key 1 = 8.66195721802725Hz */\r
+       0x00092d51,     /* key 2 = 9.17702399741899Hz */\r
+       0x0009b904,     /* key 3 = 9.72271824131503Hz */\r
+       0x000a4d05,     /* key 4 = 10.3008611535272Hz */\r
+       0x000ae9d3,     /* key 5 = 10.9133822322814Hz */\r
+       0x000b8ff4,     /* key 6 = 11.5623257097386Hz */\r
+       0x000c3ff6,     /* key 7 = 12.2498573744297Hz */\r
+       0x000cfa70,     /* key 8 = 12.9782717993733Hz */\r
+       0x000dc000,     /* key 9 = 13.75Hz */\r
+       0x000e914f,     /* key 10 = 14.5676175474403Hz */\r
+       0x000f6f11,     /* key 11 = 15.4338531642539Hz */\r
+       0x00105a02,     /* key 12 = 16.3515978312874Hz */\r
+       0x001152ec,     /* key 13 = 17.3239144360545Hz */\r
+       0x00125aa2,     /* key 14 = 18.354047994838Hz */\r
+       0x00137208,     /* key 15 = 19.4454364826301Hz */\r
+       0x00149a0a,     /* key 16 = 20.6017223070544Hz */\r
+       0x0015d3a6,     /* key 17 = 21.8267644645627Hz */\r
+       0x00171fe9,     /* key 18 = 23.1246514194771Hz */\r
+       0x00187fed,     /* key 19 = 24.4997147488593Hz */\r
+       0x0019f4e0,     /* key 20 = 25.9565435987466Hz */\r
+       0x001b8000,     /* key 21 = 27.5Hz */\r
+       0x001d229e,     /* key 22 = 29.1352350948806Hz */\r
+       0x001ede22,     /* key 23 = 30.8677063285078Hz */\r
+       0x0020b404,     /* key 24 = 32.7031956625748Hz */\r
+       0x0022a5d8,     /* key 25 = 34.647828872109Hz */\r
+       0x0024b545,     /* key 26 = 36.7080959896759Hz */\r
+       0x0026e410,     /* key 27 = 38.8908729652601Hz */\r
+       0x00293414,     /* key 28 = 41.2034446141087Hz */\r
+       0x002ba74d,     /* key 29 = 43.6535289291255Hz */\r
+       0x002e3fd2,     /* key 30 = 46.2493028389543Hz */\r
+       0x0030ffda,     /* key 31 = 48.9994294977187Hz */\r
+       0x0033e9c0,     /* key 32 = 51.9130871974931Hz */\r
+       0x00370000,     /* key 33 = 55Hz */\r
+       0x003a453d,     /* key 34 = 58.2704701897612Hz */\r
+       0x003dbc44,     /* key 35 = 61.7354126570155Hz */\r
+       0x00416809,     /* key 36 = 65.4063913251497Hz */\r
+       0x00454bb0,     /* key 37 = 69.295657744218Hz */\r
+       0x00496a8b,     /* key 38 = 73.4161919793519Hz */\r
+       0x004dc820,     /* key 39 = 77.7817459305202Hz */\r
+       0x00526829,     /* key 40 = 82.4068892282175Hz */\r
+       0x00574e9b,     /* key 41 = 87.307057858251Hz */\r
+       0x005c7fa4,     /* key 42 = 92.4986056779086Hz */\r
+       0x0061ffb5,     /* key 43 = 97.9988589954373Hz */\r
+       0x0067d380,     /* key 44 = 103.826174394986Hz */\r
+       0x006e0000,     /* key 45 = 110Hz */\r
+       0x00748a7b,     /* key 46 = 116.540940379522Hz */\r
+       0x007b7888,     /* key 47 = 123.470825314031Hz */\r
+       0x0082d012,     /* key 48 = 130.812782650299Hz */\r
+       0x008a9760,     /* key 49 = 138.591315488436Hz */\r
+       0x0092d517,     /* key 50 = 146.832383958704Hz */\r
+       0x009b9041,     /* key 51 = 155.56349186104Hz */\r
+       0x00a4d053,     /* key 52 = 164.813778456435Hz */\r
+       0x00ae9d36,     /* key 53 = 174.614115716502Hz */\r
+       0x00b8ff49,     /* key 54 = 184.997211355817Hz */\r
+       0x00c3ff6a,     /* key 55 = 195.997717990875Hz */\r
+       0x00cfa700,     /* key 56 = 207.652348789973Hz */\r
+       0x00dc0000,     /* key 57 = 220Hz */\r
+       0x00e914f6,     /* key 58 = 233.081880759045Hz */\r
+       0x00f6f110,     /* key 59 = 246.941650628062Hz */\r
+       0x0105a025,     /* key 60 = 261.625565300599Hz */\r
+       0x01152ec0,     /* key 61 = 277.182630976872Hz */\r
+       0x0125aa2e,     /* key 62 = 293.664767917408Hz */\r
+       0x01372082,     /* key 63 = 311.126983722081Hz */\r
+       0x0149a0a7,     /* key 64 = 329.62755691287Hz */\r
+       0x015d3a6d,     /* key 65 = 349.228231433004Hz */\r
+       0x0171fe92,     /* key 66 = 369.994422711634Hz */\r
+       0x0187fed4,     /* key 67 = 391.995435981749Hz */\r
+       0x019f4e00,     /* key 68 = 415.304697579945Hz */\r
+       0x01b80000,     /* key 69 = 440Hz */\r
+       0x01d229ec,     /* key 70 = 466.16376151809Hz */\r
+       0x01ede220,     /* key 71 = 493.883301256124Hz */\r
+       0x020b404a,     /* key 72 = 523.251130601197Hz */\r
+       0x022a5d81,     /* key 73 = 554.365261953744Hz */\r
+       0x024b545c,     /* key 74 = 587.329535834815Hz */\r
+       0x026e4104,     /* key 75 = 622.253967444162Hz */\r
+       0x0293414f,     /* key 76 = 659.25511382574Hz */\r
+       0x02ba74da,     /* key 77 = 698.456462866008Hz */\r
+       0x02e3fd24,     /* key 78 = 739.988845423269Hz */\r
+       0x030ffda9,     /* key 79 = 783.990871963499Hz */\r
+       0x033e9c01,     /* key 80 = 830.60939515989Hz */\r
+       0x03700000,     /* key 81 = 880Hz */\r
+       0x03a453d8,     /* key 82 = 932.32752303618Hz */\r
+       0x03dbc440,     /* key 83 = 987.766602512248Hz */\r
+       0x04168094,     /* key 84 = 1046.50226120239Hz */\r
+       0x0454bb03,     /* key 85 = 1108.73052390749Hz */\r
+       0x0496a8b8,     /* key 86 = 1174.65907166963Hz */\r
+       0x04dc8208,     /* key 87 = 1244.50793488832Hz */\r
+       0x0526829e,     /* key 88 = 1318.51022765148Hz */\r
+       0x0574e9b5,     /* key 89 = 1396.91292573202Hz */\r
+       0x05c7fa49,     /* key 90 = 1479.97769084654Hz */\r
+       0x061ffb53,     /* key 91 = 1567.981743927Hz */\r
+       0x067d3802,     /* key 92 = 1661.21879031978Hz */\r
+       0x06e00000,     /* key 93 = 1760Hz */\r
+       0x0748a7b1,     /* key 94 = 1864.65504607236Hz */\r
+       0x07b78880,     /* key 95 = 1975.5332050245Hz */\r
+       0x082d0128,     /* key 96 = 2093.00452240479Hz */\r
+       0x08a97607,     /* key 97 = 2217.46104781498Hz */\r
+       0x092d5171,     /* key 98 = 2349.31814333926Hz */\r
+       0x09b90410,     /* key 99 = 2489.01586977665Hz */\r
+       0x0a4d053c,     /* key 100 = 2637.02045530296Hz */\r
+       0x0ae9d36b,     /* key 101 = 2793.82585146403Hz */\r
+       0x0b8ff493,     /* key 102 = 2959.95538169308Hz */\r
+       0x0c3ff6a7,     /* key 103 = 3135.96348785399Hz */\r
+       0x0cfa7005,     /* key 104 = 3322.43758063956Hz */\r
+       0x0dc00000,     /* key 105 = 3520Hz */\r
+       0x0e914f62,     /* key 106 = 3729.31009214472Hz */\r
+       0x0f6f1100,     /* key 107 = 3951.06641004899Hz */\r
+       0x105a0250,     /* key 108 = 4186.00904480958Hz */\r
+       0x1152ec0e,     /* key 109 = 4434.92209562995Hz */\r
+       0x125aa2e3,     /* key 110 = 4698.63628667852Hz */\r
+       0x13720820,     /* key 111 = 4978.03173955329Hz */\r
+       0x149a0a79,     /* key 112 = 5274.04091060592Hz */\r
+       0x15d3a6d6,     /* key 113 = 5587.65170292806Hz */\r
+       0x171fe927,     /* key 114 = 5919.91076338615Hz */\r
+       0x187fed4e,     /* key 115 = 6271.92697570799Hz */\r
+       0x19f4e00a,     /* key 116 = 6644.87516127912Hz */\r
+       0x1b800000,     /* key 117 = 7040Hz */\r
+       0x1d229ec4,     /* key 118 = 7458.62018428944Hz */\r
+       0x1ede2200,     /* key 119 = 7902.13282009799Hz */\r
+       0x20b404a1,     /* key 120 = 8372.01808961916Hz */\r
+       0x22a5d81c,     /* key 121 = 8869.84419125991Hz */\r
+       0x24b545c7,     /* key 122 = 9397.27257335704Hz */\r
+       0x26e41040,     /* key 123 = 9956.06347910659Hz */\r
+       0x293414f2,     /* key 124 = 10548.0818212118Hz */\r
+       0x2ba74dac,     /* key 125 = 11175.3034058561Hz */\r
+       0x2e3fd24f,     /* key 126 = 11839.8215267723Hz */\r
+       0x30ffda9c      /* key 127 = 12543.853951416Hz */\r
+};\r
+\r
+static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) {\r
+       return midikeys_freqs[key&0x7F];\r
+}\r
+\r
+static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) {\r
+       unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */\r
+       unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */\r
+       unsigned int i,freen=~0;\r
+\r
+       for (i=0;i < ADLIB_FM_VOICES;i++) {\r
+               if (midi_notes[i].busy) {\r
+                       if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key)\r
+                               return &midi_notes[i];\r
+               }\r
+               else {\r
+                       if (freen == ~0) freen = i;\r
+               }\r
+       }\r
+\r
+       if (do_alloc && freen != ~0) return &midi_notes[freen];\r
+       return NULL;\r
+}\r
+\r
+static void drop_fm_note(struct midi_channel *ch,unsigned char key) {\r
+       unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */\r
+       unsigned int i;\r
+\r
+       for (i=0;i < ADLIB_FM_VOICES;i++) {\r
+               if (midi_notes[i].busy && midi_notes[i].note_channel == ach) {\r
+                       midi_notes[i].busy = 0;\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {\r
+       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0);\r
+       uint32_t freq = midi_note_freq(ch,key);\r
+       unsigned int ach;\r
+\r
+       if (note == NULL) return;\r
+\r
+       note->busy = 1;\r
+       note->note_number = key;\r
+       note->note_velocity = vel;\r
+       note->note_track = (unsigned int)(t - midi_trk);\r
+       note->note_channel = (unsigned int)(ch - midi_ch);\r
+       ach = (unsigned int)(note - midi_notes); /* which FM channel? */\r
+       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);\r
+       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */\r
+       adlib_fm[ach].mod.sustain_level = vel >> 3;\r
+       adlib_fm[ach].mod.key_on = 1;\r
+       adlib_update_groupA0(ach,&adlib_fm[ach]);\r
+}\r
+\r
+static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {\r
+       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1);\r
+       uint32_t freq = midi_note_freq(ch,key);\r
+       unsigned int ach;\r
+\r
+       /* HACK: Ignore percussion */\r
+       if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ ||\r
+               (ch->program >= 112 && ch->program <= 119)/*Percussive*/ ||\r
+               ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/)\r
+               return;\r
+\r
+       if (note == NULL) {\r
+               /* then we'll have to knock one off to make room */\r
+               drop_fm_note(ch,key);\r
+               note = get_fm_note(t,ch,key,1);\r
+               if (note == NULL) return;\r
+       }\r
+\r
+       note->busy = 1;\r
+       note->note_number = key;\r
+       note->note_velocity = vel;\r
+       note->note_track = (unsigned int)(t - midi_trk);\r
+       note->note_channel = (unsigned int)(ch - midi_ch);\r
+       ach = (unsigned int)(note - midi_notes); /* which FM channel? */\r
+       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);\r
+       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */\r
+       adlib_fm[ach].mod.sustain_level = vel >> 3;\r
+       adlib_fm[ach].mod.key_on = 1;\r
+       adlib_update_groupA0(ach,&adlib_fm[ach]);\r
+}\r
+\r
+static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) {\r
+       struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0);\r
+       uint32_t freq = midi_note_freq(ch,key);\r
+       unsigned int ach;\r
+\r
+       if (note == NULL) return;\r
+\r
+       note->busy = 0;\r
+       ach = (unsigned int)(note - midi_notes); /* which FM channel? */\r
+       adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536);\r
+       adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */\r
+       adlib_fm[ach].mod.sustain_level = vel >> 3;\r
+       adlib_fm[ach].mod.key_on = 0;\r
+       adlib_update_groupA0(ach,&adlib_fm[ach]);\r
+}\r
+\r
+static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) {\r
+}\r
+\r
+static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) {\r
+       ch->program = inst;\r
+}\r
+\r
+static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) {\r
+}\r
+\r
+static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) {\r
+}\r
+\r
+unsigned long midi_trk_read_delta(struct midi_track *t) {\r
+       unsigned long tc = 0;\r
+       unsigned char c = 0,b;\r
+\r
+       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */\r
+       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence)\r
+               return tc;\r
+\r
+       while (c < 4) {\r
+               b = midi_trk_read(t);\r
+               tc = (tc << 7UL) + (unsigned long)(b&0x7F);\r
+               if (!(b&0x80)) break;\r
+               c++;\r
+       }\r
+\r
+       return tc;\r
+}\r
+\r
+void midi_tick_track(unsigned int i) {\r
+       struct midi_track *t = midi_trk + i;\r
+       struct midi_channel *ch;\r
+       unsigned char b,c,d;\r
+       int cnt=0;\r
+\r
+       /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */\r
+       if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) {\r
+               t->eof = 1;\r
+               return;\r
+       }\r
+\r
+       t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note;\r
+       while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) {\r
+               t->us_tick_cnt_mtpq -= t->us_per_quarter_note;\r
+               cnt++;\r
+\r
+               while (t->wait == 0) {\r
+                       if ((unsigned long)t->read >= (unsigned long)t->fence) {\r
+                               t->eof = 1;\r
+                               break;\r
+                       }\r
+\r
+                       /* read pointer should be pointing at MIDI event bytes, just after the time delay */\r
+                       b = midi_trk_read(t);\r
+                       if (b&0x80) {\r
+                               if (b < 0xF8) {\r
+                                       if (b >= 0xF0)\r
+                                               t->last_status = 0;\r
+                                       else\r
+                                               t->last_status = b;\r
+                               }\r
+                               if (b != 0x00 && ((b&0xF8) != 0xF0))\r
+                                       c = midi_trk_read(t);\r
+                       }\r
+                       else {\r
+                               /* blegh. last status */\r
+                               c = b;\r
+                               b = t->last_status;\r
+                       }\r
+                       switch (b>>4) {\r
+                               case 0x8: { /* note off */\r
+                                       d = midi_trk_read(t);\r
+                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */\r
+                                       on_key_off(t,ch,c,d);\r
+                                       } break;\r
+                               case 0x9: { /* note on */\r
+                                       d = midi_trk_read(t);\r
+                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */\r
+                                       if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */\r
+                                       else on_key_off(t,ch,c,d);\r
+                                       } break;\r
+                               case 0xA: { /* polyphonic aftertouch */\r
+                                       d = midi_trk_read(t);\r
+                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */\r
+                                       on_key_aftertouch(t,ch,c,d);\r
+                                       } break;\r
+                               case 0xB: { /* control change */\r
+                                       d = midi_trk_read(t);\r
+                                       ch = midi_ch + (b&0xF); /* c=key d=velocity */\r
+                                       on_control_change(t,ch,c,d);\r
+                                       } break;\r
+                               case 0xC: { /* program change */\r
+                                       on_program_change(t,ch,c); /* c=instrument d=not used */\r
+                                       } break;\r
+                               case 0xD: { /* channel aftertouch */\r
+                                       on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */\r
+                                       } break;\r
+                               case 0xE: { /* pitch bend */\r
+                                       d = midi_trk_read(t);\r
+                                       on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */\r
+                                       } break;\r
+                               case 0xF: { /* event */\r
+                                       if (b == 0xFF) {\r
+                                               if (c == 0x7F) { /* c=type d=len */\r
+                                                       unsigned long len = midi_trk_read_delta(t);\r
+//                                                     fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence);\r
+                                                       if (len < 512UL) {\r
+                                                               /* unknown */\r
+                                                               midi_trk_skip(t,len);\r
+                                                       }\r
+                                                       else {\r
+                                                               midi_trk_end(t);\r
+                                                       }\r
+                                               }\r
+                                               else if (c < 0x7F) {\r
+                                                       d = midi_trk_read(t);\r
+\r
+                                                       if (c == 0x51 && d >= 3) {\r
+                                                               d -= 3;\r
+                                                               t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+\r
+                                                                       ((unsigned long)midi_trk_read(t)<<8UL)+\r
+                                                                       ((unsigned long)midi_trk_read(t)<<0UL);\r
+\r
+                                                               if (1/*TODO: If format 0 or format 1*/) {\r
+                                                                       /* Ugh. Unless format 2, the tempo applies to all tracks */\r
+                                                                       int j;\r
+\r
+                                                                       for (j=0;j < midi_trk_count;j++) {\r
+                                                                               if (j != i) midi_trk[j].us_per_quarter_note =\r
+                                                                                       t->us_per_quarter_note;\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+                                                       else {\r
+//                                                             fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence);\r
+                                                       }\r
+\r
+                                                       midi_trk_skip(t,d);\r
+                                               }\r
+                                               else {\r
+                                                       fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence);\r
+                                               }\r
+                                       }\r
+                                       else {\r
+                                               unsigned long len = midi_trk_read_delta(t);\r
+//                                             fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence);\r
+                                               midi_trk_skip(t,len);\r
+                                       }\r
+                                       } break;\r
+                               default:\r
+                                       if (b != 0x00) {\r
+                                               fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence);\r
+                                               midi_trk_end(t);\r
+                                       }\r
+                                       break;\r
+                       };\r
+\r
+                       /* and then read the next event */\r
+                       t->wait = midi_trk_read_delta(t);\r
+               }\r
+               if (t->wait != 0) {\r
+                       t->wait--;\r
+               }\r
+       }\r
+}\r
+\r
+void adlib_shut_up();\r
+void midi_reset_tracks();\r
+void midi_reset_channels();\r
+\r
+void midi_tick() {\r
+       if (midi_playing) {\r
+               unsigned int i;\r
+               int eof=0;\r
+\r
+               for (i=0;i < midi_trk_count;i++) {\r
+                       midi_tick_track(i);\r
+                       eof += midi_trk[i].eof?1:0;\r
+               }\r
+\r
+               if (eof >= midi_trk_count) {\r
+                       adlib_shut_up();\r
+                       midi_reset_tracks();\r
+                       midi_reset_channels();\r
+               }\r
+       }\r
+}\r
+\r
+/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */\r
+void interrupt irq0() {\r
+//     midi_tick();\r
+       irq0_ticks++;\r
+       if ((irq0_cnt += irq0_add) >= irq0_max) {\r
+               irq0_cnt -= irq0_max;\r
+               old_irq0();\r
+       }\r
+       else {\r
+               p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI);\r
+       }\r
+}\r
+\r
+void adlib_shut_up() {\r
+       int i;\r
+\r
+       memset(adlib_fm,0,sizeof(adlib_fm));\r
+       memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));\r
+       for (i=0;i < adlib_fm_voices;i++) {\r
+               struct adlib_fm_operator *f;\r
+               f = &adlib_fm[i].mod;\r
+               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\r
+               f = &adlib_fm[i].car;\r
+               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\r
+       }\r
+\r
+       for (i=0;i < adlib_fm_voices;i++) {\r
+               struct adlib_fm_operator *f;\r
+\r
+               midi_notes[i].busy = 0;\r
+               midi_notes[i].note_channel = 0;\r
+\r
+               f = &adlib_fm[i].mod;\r
+               f->mod_multiple = 1;\r
+               f->total_level = 63 - 16;\r
+               f->attack_rate = 15;\r
+               f->decay_rate = 4;\r
+               f->sustain_level = 0;\r
+               f->release_rate = 8;\r
+               f->f_number = 400;\r
+               f->sustain = 1;\r
+               f->octave = 4;\r
+               f->key_on = 0;\r
+\r
+               f = &adlib_fm[i].car;\r
+               f->mod_multiple = 1;\r
+               f->total_level = 63 - 16;\r
+               f->attack_rate = 15;\r
+               f->decay_rate = 4;\r
+               f->sustain_level = 0;\r
+               f->release_rate = 8;\r
+               f->f_number = 0;\r
+               f->sustain = 1;\r
+               f->octave = 0;\r
+               f->key_on = 0;\r
+       }\r
+\r
+       adlib_apply_all();\r
+}\r
+\r
+void midi_reset_track(unsigned int i) {\r
+       struct midi_track *t;\r
+\r
+       if (i >= MIDI_MAX_TRACKS) return;\r
+       t = &midi_trk[i];\r
+       t->eof = 0;\r
+       t->last_status = 0;\r
+       t->us_tick_cnt_mtpq = 0;\r
+       t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */\r
+       t->read = midi_trk[i].raw;\r
+       t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */\r
+}\r
+\r
+void midi_reset_tracks() {\r
+       int i;\r
+\r
+       for (i=0;i < midi_trk_count;i++)\r
+               midi_reset_track(i);\r
+}\r
+\r
+void midi_reset_channels() {\r
+       int i;\r
+\r
+       for (i=0;i < MIDI_MAX_CHANNELS;i++) {\r
+               midi_ch[i].program = 0;\r
+       }\r
+}\r
+\r
+int load_midi_file(const char *path) {\r
+       unsigned char tmp[256];\r
+       unsigned int tracks=0;\r
+       unsigned int tracki=0;\r
+       int fd;\r
+\r
+       fd = open(path,O_RDONLY|O_BINARY);\r
+       if (fd < 0) {\r
+               printf("Failed to load file %s\n",path);\r
+               return 0;\r
+       }\r
+\r
+       ticks_per_quarter_note = 0;\r
+       while (read(fd,tmp,8) == 8) {\r
+               uint32_t sz;\r
+\r
+               sz =    ((uint32_t)tmp[4] << (uint32_t)24) |\r
+                       ((uint32_t)tmp[5] << (uint32_t)16) |\r
+                       ((uint32_t)tmp[6] << (uint32_t)8) |\r
+                       ((uint32_t)tmp[7] << (uint32_t)0);\r
+               if (!memcmp(tmp,"MThd",4)) {\r
+                       unsigned short t,tdiv;\r
+\r
+                       if (sz < 6 || sz > 255) {\r
+                               fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz);\r
+                               goto err;\r
+                       }\r
+                       if (read(fd,tmp,(int)sz) != (int)sz) {\r
+                               fprintf(stderr,"MThd read error\n");\r
+                               goto err;\r
+                       }\r
+\r
+                       /* byte 0-1 = format type (0,1 or 2) */\r
+                       /* byte 2-3 = number of tracks */\r
+                       /* byte 4-5 = time divison */\r
+                       t = tmp[1] | (tmp[0] << 8);\r
+                       if (t > 1) {\r
+                               fprintf(stderr,"MThd type %u not supported\n",t);\r
+                               goto err; /* we only take type 0 or 1, don't support 2 */\r
+                       }\r
+                       tracks = tmp[3] | (tmp[2] << 8);\r
+                       if (tracks > MIDI_MAX_TRACKS) {\r
+                               fprintf(stderr,"MThd too many (%u) tracks\n",tracks);\r
+                               goto err;\r
+                       }\r
+                       tdiv = tmp[5] | (tmp[4] << 8);\r
+                       if (tdiv & 0x8000) {\r
+                               fprintf(stderr,"MThd SMPTE time division not supported\n");\r
+                               goto err; /* we do not support the SMPTE form */\r
+                       }\r
+                       if (tdiv == 0) {\r
+                               fprintf(stderr,"MThd time division == 0\n");\r
+                               goto err;\r
+                       }\r
+                       ticks_per_quarter_note = tdiv;\r
+               }\r
+               else if (!memcmp(tmp,"MTrk",4)) {\r
+                       if (sz == 0UL) continue;\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+                       if (sz > (640UL << 10UL)) goto err; /* 640KB */\r
+#elif TARGET_MSDOS == 32\r
+                       if (sz > (1UL << 20UL)) goto err; /* 1MB */\r
+#else\r
+                       if (sz > (60UL << 10UL)) goto err; /* 60KB */\r
+#endif\r
+                       if (tracki >= MIDI_MAX_TRACKS) goto err;\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+                       {\r
+                               unsigned segv;\r
+\r
+                               /* NTS: _fmalloc() is still limited to 64KB sizes */\r
+                               if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err;\r
+                               midi_trk[tracki].raw = MK_FP(segv,0);\r
+                       }\r
+#else\r
+                       midi_trk[tracki].raw = malloc(sz);\r
+#endif\r
+                       if (midi_trk[tracki].raw == NULL) goto err;\r
+                       midi_trk[tracki].read = midi_trk[tracki].raw;\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+                       {\r
+                               unsigned char far *p = midi_trk[tracki].raw;\r
+                               unsigned long rem = (unsigned long)sz;\r
+                               unsigned long cando;\r
+                               unsigned read;\r
+\r
+                               while (rem != 0UL) {\r
+                                       read = 0;\r
+\r
+                                       cando = 0x10000UL - (unsigned long)FP_OFF(p);\r
+                                       if (cando > rem) cando = rem;\r
+                                       if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */\r
+\r
+                                       if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err;\r
+                                       if (read != (unsigned)cando) goto err;\r
+\r
+                                       rem -= cando;\r
+                                       if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL)\r
+                                               p = MK_FP(FP_SEG(p)+0x1000,0);\r
+                                       else\r
+                                               p += (unsigned)cando;\r
+                               }\r
+\r
+                               cando = farptr2phys(p);\r
+                               midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF);\r
+                       }\r
+#else\r
+                       midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz;\r
+                       if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err;\r
+#endif\r
+                       tracki++;\r
+               }\r
+               else {\r
+                       fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]);\r
+                       goto err;\r
+               }\r
+       }\r
+       if (tracki == 0 || ticks_per_quarter_note == 0) goto err;\r
+       midi_trk_count = tracki;\r
+\r
+       fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note);\r
+\r
+       close(fd);\r
+       return 1;\r
+err:\r
+       close(fd);\r
+       return 0;\r
+}\r
+\r
+int main(int argc,char **argv) {\r
+       unsigned long ptick;\r
+       int i,c;\r
+\r
+       printf("ADLIB FM test program\n");\r
+       if (argc < 2) {\r
+               printf("You must specify a MIDI file to play\n");\r
+               return 1;\r
+       }\r
+\r
+       if (!probe_vga()) {\r
+               printf("Cannot init VGA\n");\r
+               return 1;\r
+       }\r
+       if (!init_adlib()) {\r
+               printf("Cannot init library\n");\r
+               return 1;\r
+       }\r
+       if (!probe_8254()) { /* we need the timer to keep time with the music */\r
+               printf("8254 timer not found\n");\r
+               return 1;\r
+       }\r
+\r
+       for (i=0;i < MIDI_MAX_TRACKS;i++) {\r
+               midi_trk[i].raw = NULL;\r
+               midi_trk[i].read = NULL;\r
+               midi_trk[i].fence = NULL;\r
+       }\r
+\r
+       if (load_midi_file(argv[1]) == 0) {\r
+               printf("Failed to load MIDI\n");\r
+               return 1;\r
+       }\r
+\r
+       write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); /* tick faster at 100Hz please */\r
+       irq0_cnt = 0;\r
+       irq0_add = 182;\r
+       irq0_max = 1000; /* about 18.2Hz */\r
+       old_irq0 = _dos_getvect(8);/*IRQ0*/\r
+       _dos_setvect(8,irq0);\r
+\r
+       adlib_shut_up();\r
+       midi_reset_channels();\r
+       midi_reset_tracks();\r
+       _cli();\r
+       irq0_ticks = ptick = 0;\r
+       _sti();\r
+       midi_playing = 1;\r
+\r
+       while (1) {\r
+               unsigned long adv;\r
+\r
+               _cli();\r
+               adv = irq0_ticks - ptick;\r
+               if (adv >= 100UL) adv = 100UL;\r
+               ptick = irq0_ticks;\r
+               _sti();\r
+\r
+               while (adv != 0) {\r
+                       midi_tick();\r
+                       adv--;\r
+               }\r
+\r
+               if (kbhit()) {\r
+                       c = getch();\r
+                       if (c == 0) c = getch() << 8;\r
+\r
+                       if (c == 27) {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       midi_playing = 0;\r
+       adlib_shut_up();\r
+       shutdown_adlib();\r
+       _dos_setvect(8,old_irq0);\r
+       write_8254_system_timer(0); /* back to normal 18.2Hz */\r
+\r
+       for (i=0;i < MIDI_MAX_TRACKS;i++) {\r
+               if (midi_trk[i].raw) {\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+                       _dos_freemem(FP_SEG(midi_trk[i].raw)); /* NTS: Because we allocated with _dos_allocmem */\r
+#else\r
+                       free(midi_trk[i].raw);\r
+#endif\r
+                       midi_trk[i].raw = NULL;\r
+               }\r
+               midi_trk[i].fence = NULL;\r
+               midi_trk[i].read = NULL;\r
+       }\r
+\r
+       return 0;\r
+}\r
index 73b47057b54dd2825819ef00369366164407a64b..ade69519dd91a3b03368d933c2295b63fa0481a1 100755 (executable)
-/* miditest.c
- *
- * Adlib OPL2/OPL3 FM synthesizer chipset test program.
- * Play MIDI file using the OPLx synthesizer (well, poorly anyway)
- * (C) 2010-2012 Jonathan Campbell.
- * Hackipedia DOS library.
- *
- * This code is licensed under the LGPL.
- * <insert LGPL legal text here>
- *
- * Compiles for intended target environments:
- *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]
- */
-
-#include "src/lib/midi.h"
-
-int main(int argc,char **argv) {
-       unsigned long ptick;
-       int i,c;
-
-       printf("ADLIB FM test program\n");
-       if (argc < 2) {
-               printf("You must specify a MIDI file to play\n");
-               return 1;
-       }
-
-       /*if (!probe_vga()) {
-               printf("Cannot init VGA\n");
-               return 1;
-       }*/
-       if (!init_adlib()) {
-               printf("Cannot init library\n");
-               return 1;
-       }
-       if (!probe_8254()) { /* we need the timer to keep time with the music */
-               printf("8254 timer not found\n");
-               return 1;
-       }
-
-       for (i=0;i < MIDI_MAX_TRACKS;i++) {
-               midi_trk[i].raw = NULL;
-               midi_trk[i].read = NULL;
-               midi_trk[i].fence = NULL;
-       }
-
-       if (load_midi_file(argv[1]) == 0) {
-               printf("Failed to load MIDI\n");
-               return 1;
-       }
-
-       write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); /* tick faster at 100Hz please */
-       irq0_cnt = 0;
-       irq0_add = 182;
-       irq0_max = 1000; /* about 18.2Hz */
-       old_irq0 = _dos_getvect(8);/*IRQ0*/
-       _dos_setvect(8,irq0);
-
-       //adlib_shut_up();
-       midi_reset_channels();
-       midi_reset_tracks();
-       _cli();
-       irq0_ticks = ptick = 0;
-       _sti();
-       midi_playing = 1;
-
-       while (1) {
-               unsigned long adv;
-
-               _cli();
-               adv = irq0_ticks - ptick;
-               //adv = ptick;
-               if (adv >= 100UL) adv = 100UL;
-               ptick = irq0_ticks;
-               //ptick++;
-               _sti();
-
-               while (adv != 0) {
-                       midi_tick();
-                       adv--;
-               }
-
-               if (kbhit()) {
-                       c = getch();
-                       if (c == 0) c = getch() << 8;
-
-                       if (c == 27) {
-                               break;
-                       }
-               }
-       }
-
-       midi_playing = 0;
-       //adlib_shut_up();
-       shutdown_adlib();
-       _dos_setvect(8,old_irq0);
-       write_8254_system_timer(0); /* back to normal 18.2Hz */
-
-       for (i=0;i < MIDI_MAX_TRACKS;i++) {
-               if (midi_trk[i].raw) {
-#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))
-                       _dos_freemem(FP_SEG(midi_trk[i].raw)); /* NTS: Because we allocated with _dos_allocmem */
-#else
-                       free(midi_trk[i].raw);
-#endif
-                       midi_trk[i].raw = NULL;
-               }
-               midi_trk[i].fence = NULL;
-               midi_trk[i].read = NULL;
-       }
-
-       return 0;
-}
+/* miditest.c\r
+ *\r
+ * Adlib OPL2/OPL3 FM synthesizer chipset test program.\r
+ * Play MIDI file using the OPLx synthesizer (well, poorly anyway)\r
+ * (C) 2010-2012 Jonathan Campbell.\r
+ * Hackipedia DOS library.\r
+ *\r
+ * This code is licensed under the LGPL.\r
+ * <insert LGPL legal text here>\r
+ *\r
+ * Compiles for intended target environments:\r
+ *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]\r
+ */\r
+\r
+#include "src/lib/midi.h"\r
+\r
+int main(int argc,char **argv) {\r
+       unsigned long ptick;\r
+       int i,c;\r
+\r
+       printf("ADLIB FM test program\n");\r
+       if (argc < 2) {\r
+               printf("You must specify a MIDI file to play\n");\r
+               return 1;\r
+       }\r
+\r
+       /*if (!probe_vga()) {\r
+               printf("Cannot init VGA\n");\r
+               return 1;\r
+       }*/\r
+       if (!init_adlib()) {\r
+               printf("Cannot init library\n");\r
+               return 1;\r
+       }\r
+       if (!probe_8254()) { /* we need the timer to keep time with the music */\r
+               printf("8254 timer not found\n");\r
+               return 1;\r
+       }\r
+\r
+       for (i=0;i < MIDI_MAX_TRACKS;i++) {\r
+               midi_trk[i].raw = NULL;\r
+               midi_trk[i].read = NULL;\r
+               midi_trk[i].fence = NULL;\r
+       }\r
+\r
+       if (load_midi_file(argv[1]) == 0) {\r
+               printf("Failed to load MIDI\n");\r
+               return 1;\r
+       }\r
+\r
+       write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); /* tick faster at 100Hz please */\r
+       irq0_cnt = 0;\r
+       irq0_add = 182;\r
+       irq0_max = 1000; /* about 18.2Hz */\r
+       old_irq0 = _dos_getvect(8);/*IRQ0*/\r
+       _dos_setvect(8,irq0);\r
+\r
+       //adlib_shut_up();\r
+       midi_reset_channels();\r
+       midi_reset_tracks();\r
+       _cli();\r
+       irq0_ticks = ptick = 0;\r
+       _sti();\r
+       midi_playing = 1;\r
+\r
+       while (1) {\r
+               unsigned long adv;\r
+\r
+               _cli();\r
+               adv = irq0_ticks - ptick;\r
+               //adv = ptick;\r
+               if (adv >= 100UL) adv = 100UL;\r
+               ptick = irq0_ticks;\r
+               //ptick++;\r
+               _sti();\r
+\r
+               while (adv != 0) {\r
+                       midi_tick();\r
+                       adv--;\r
+               }\r
+\r
+               if (kbhit()) {\r
+                       c = getch();\r
+                       if (c == 0) c = getch() << 8;\r
+\r
+                       if (c == 27) {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       midi_playing = 0;\r
+       //adlib_shut_up();\r
+       shutdown_adlib();\r
+       _dos_setvect(8,old_irq0);\r
+       write_8254_system_timer(0); /* back to normal 18.2Hz */\r
+\r
+       for (i=0;i < MIDI_MAX_TRACKS;i++) {\r
+               if (midi_trk[i].raw) {\r
+#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__))\r
+                       _dos_freemem(FP_SEG(midi_trk[i].raw)); /* NTS: Because we allocated with _dos_allocmem */\r
+#else\r
+                       free(midi_trk[i].raw);\r
+#endif\r
+                       midi_trk[i].raw = NULL;\r
+               }\r
+               midi_trk[i].fence = NULL;\r
+               midi_trk[i].read = NULL;\r
+       }\r
+\r
+       return 0;\r
+}\r
index 2746ca4f1cc500316ba210f54ce75dc116b13871..e638df1b06c0677b09dce6d45fe3b32e956024a8 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "src/lib/scroll16.h"
-#include "src/lib/16_timer.h"
-#include "src/lib/wcpu/wcpu.h"
-
-//#define FADE
-#define MODEX  //this is for mode x initiating
-
-//word far *clock= (word far*) 0x046C; /* 18.2hz clock */
-//bitmap_t *p;
-global_game_variables_t gvar;
-static map_t map;
-player_t player[MaxPlayers];
-map_view_t mv[4];
-//word pn=0; //i forgot ww
-float t;
-sword bakapee;
-pan_t pan;
-//debugswitches
-boolean panswitch=0;
-//extern boolean pageflipflop=1;
-       unsigned int i;
-       const char *cpus;
-       //static int persist_aniframe = 0;    /* gonna be increased to 1 before being used, so 0 is ok for default */
-
-       //map_view_db_t pgid[4];
-       word pg;
-//#ifdef FADE
-       static word paloffset=0;
-       byte *dpal;
-//#endif
-       byte *gpal;
-       byte *ptr;
-       byte *mappalptr;
-
-void main(int argc, char *argv[])
-{
-       byte *mesg=malloc(sizeof(dword));
-
-       if(argv[1]) bakapee = atoi(argv[1]);
-       else bakapee = 1;
-
-       // DOSLIB: check our environment
-       probe_dos();
-
-       // DOSLIB: what CPU are we using?
-       // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS.
-       //      So this code by itself shouldn't care too much what CPU it's running on. Except that other
-       //      parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for
-       //      the CPU to carry out tasks. --J.C.
-       cpu_probe();
-
-       // DOSLIB: check for VGA
-       if (!probe_vga()) {
-               printf("VGA probe failed\n");
-               return;
-       }
-       // hardware must be VGA or higher!
-       if (!(vga_state.vga_flags & VGA_IS_VGA)) {
-               printf("This program requires VGA or higher graphics hardware\n");
-               return;
-       }
-
-       if (_DEBUG_INIT() == 0) {
-#ifdef DEBUGSERIAL
-               printf("WARNING: Failed to initialize DEBUG output\n");
-#endif
-       }
-       _DEBUG("Serial debug output started\n"); // NTS: All serial output must end messages with newline, or DOSBox-X will not emit text to log
-       _DEBUGF("Serial debug output printf test %u %u %u\n",1U,2U,3U);
-
-       pan.pn=1;
-
-       start_timer(&gvar);
-
-       /* create the map */
-       fprintf(stderr, "testing map load~      ");
-       loadmap("data/test.map", &map);
-       chkmap(&map, 0);
-       printf("chkmap ok       ");
-       fprintf(stderr, "yay map loaded~~\n");
-
-       /* draw the tiles */
-#ifdef MODEX
-       ptr = map.data;
-       //mappalptr = map.tiles->btdata->palette;
-
-       /* data */
-       player[0].data = malloc(48*128); //TODO use exmm
-       *player[0].data = bitmapLoadPcx("data/chikyuu.pcx"); // load sprite
-
-       /* create the planar buffer */
-////++++       (player[0].data) = *planar_buf_from_bitmap(&p);
-       /*++++printf("load pee!!        ");
-       pp = planar_buf_from_bitmap(&p);
-       printf("done!\n");*/
-
-#endif
-       /*      input!  */
-       IN_Startup();
-       IN_Default(0,&player,ctrl_Joystick);
-       //IN_Default(1,&player,ctrl_Joystick);
-
-       /* save the palette */
-#ifdef MODEX
-#ifdef FADE
-       dpal = modexNewPal();
-       modexPalSave(dpal);
-       modexFadeOff(4, dpal);
-#endif
-
-       textInit();
-       VGAmodeX(bakapee, 1, &gvar);
-//     printf("%dx%d\n", gvar.video.page[0].sw, gvar.video.page[0].sh);
-#ifdef FADE
-       modexPalBlack();        //reset the palette~
-#endif
-#endif
-//     printf("Total used @ before palette initiation:         %zu\n", oldfreemem-GetFreeSize());
-//++++ player[0].data.offset=(paloffset/3);
-//++++ modexPalUpdate1(&player[0].data, &paloffset, 0, 0);
-               modexPalUpdate1(player[0].data->palette);
-//++++0000             modexPalUpdate1(map.tiles->btdata->palette);
-       //printf("      %d\n", sizeof(ptmp->data));
-       //printf("1:    %d\n", paloffset);
-//++++ map.tiles->data->offset=(paloffset/3);
-       //XTmodexPalUpdate(map.tiles->data, &paloffset, 0, 0);
-//     printf("\n====\n");
-//     printf("0       paloffset=      %d\n", paloffset/3);
-//     printf("====\n\n");
-#ifdef MODEX
-#ifdef FADE
-       gpal = modexNewPal();
-       modexPalSave(gpal);
-       modexSavePalFile("data/g.pal", gpal);
-       modexPalBlack();        //so player will not see loadings~
-#endif
-#endif
-
-       /* setup camera and screen~ */
-       modexHiganbanaPageSetup(&gvar.video);
-       for(i=0;i<gvar.video.num_of_pages;i++)
-       {
-               mv[i].page = &gvar.video.page[i];
-               mv[i].map = &map;
-               mv[i].video = &gvar.video;
-               mv[i].pan       = &pan;
-       }
-
-       /* set up paging */
-       //TODO: LOAD map data and position the map in the middle of the screen if smaller then screen
-       mapGoTo(mv, 0, 0);
-       //_fmemcpy(mv[1].page->data, mv[0].page->data, mv[0].page->pagesize);
-
-       //TODO: put player in starting position of spot
-       //default player position on the viewable map
-       player[0].tx = mv[0].tx + mv[0].page->tilemidposscreenx;
-       player[0].ty = mv[0].ty + mv[0].page->tilemidposscreeny;
-       IN_initplayer(&player, 0);
-       //IN_initplayer(&player, 1);
-
-#ifndef        SPRITE
-       modexClearRegion(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);
-       //modexClearRegion(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);
-#else
-       //PBUFSFUN(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 64, 24, 32, PLAYERBMPDATA);
-       PBUFSFUN(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 64, 16, 32,   player[0].data);
-#endif
-
-       if(!pageflipflop)       modexShowPage(mv[1].page);
-       else                    modexShowPage(mv[0].page);//!(gvar.video.p)
-               shinku_fps_indicator_page = 0; // we're on page 1 now, shinku(). follow along please or it will not be visible.
-
-       /* buffer pages */
-//     modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 47);
-//     modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 45);
-//     {
-//             unsigned int k,j,o;
-//             /* fill screen with a distinctive pattern */
-//             for (k=0;k < vga_state.vga_width;k++) {
-//                     o = k >> 2;
-//                     vga_write_sequencer(0x02/*map mask*/,1 << (k&3));
-//                             for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride)
-//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!
-//             }
-//     }
-       modexClearRegion(mv[3].page, 0, 128, 24, 36, 15);
-
-#ifdef MODEX
-#ifdef FADE
-       modexFadeOn(4, gpal);
-#endif
-#endif
-       while(!IN_KeyDown(sc_Escape) && player[0].hp>0)
-       {
-               shinku(&gvar);
-       //top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square
-       //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction
-       //when player[0].tx or player[0].ty == 0 or player[0].tx == 20 or player[0].ty == 15 then stop because that is edge of map and you do not want to walk of the map
-
-       //player movement
-               IN_ReadControl(0,&player);
-       if(!panswitch){
-               walk(mv, player, 0);
-       }else{
-               panpagemanual(mv, player, 0);
-               //printf("      player[0].q: %d", player[0].q); printf("        player[0].d: %d\n", player[0].d);
-       }
-
-       //the scripting stuff....
-       //if(((player[0].triggerx == TRIGGX && player[0].triggery == TRIGGY) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))
-       if(((mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))] == 0) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))
-       {
-               short i;
-               for(i=800; i>=400; i--)
-               {
-                       sound(i);
-               }
-               nosound();
-       }
-       if(player[0].q == (TILEWH/(player[0].speed))+1 && player[0].info.dir != 2 && (player[0].triggerx == 5 && player[0].triggery == 5)){ player[0].hp--; }
-       //debugging binds!
-       if(IN_KeyDown(2)){ modexShowPage(mv[0].page); pan.pn=0; }
-       if(IN_KeyDown(3)){ modexShowPage(mv[1].page); pan.pn=1; }
-       if(IN_KeyDown(4)){ modexShowPage(mv[2].page); pan.pn=2; }
-       if(IN_KeyDown(4+1)){ modexShowPage(mv[3].page); pan.pn=3; }
-       if(IN_KeyDown(25)){ modexpdump(mv[0].page); modexpdump(mv[1].page);
-                IN_UserInput(1,1);
-       }       //p
-#ifdef MODEX
-#ifdef FADE
-       if(IN_KeyDown(24)){ modexPalUpdate0(gpal); paloffset=0; modexpdump(mv[0].page); modexpdump(mv[1].page);  IN_UserInput(1,1); }
-       if(IN_KeyDown(22)){
-       paloffset=0; modexPalBlack(); modexPalUpdate(player[0].data, &paloffset, 0, 0);
-       printf("1paloffset      =       %d\n", paloffset/3);
-        modexPalUpdate(map.tiles->data, &paloffset, 0, 0);
-       printf("2paloffset      =       %d\n", paloffset/3);
-        modexpdump(mv[0].page); modexpdump(mv[1].page);
-               IN_UserInput(1,1);
-       }
-#endif
-#endif
-       //pan switch
-       if(IN_KeyDown(88)){panswitch=!panswitch; IN_UserInput(1,1);}    //f12
-       if(IN_KeyDown(87))      //f11
-       {
-               pageflipflop=!pageflipflop;
-               IN_UserInput(1,1);
-//             VGAmodeX(0, 0, &gvar);
-//             IN_Shutdown();
-//             __asm
-//             {
-//                     mov ah,31h
-//                     int 21h
-//             }
-       }
-       if(IN_KeyDown(68))      //f10
-       {
-               gvar.kurokku.fpscap=!gvar.kurokku.fpscap;
-               IN_UserInput(1,1);
-       }
-       if(IN_KeyDown(67))      //f9
-       {
-               modexClearRegion(mv[1].page, 0, 0, mv[1].page->width, mv[1].page->height, 2);
-               modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 3);
-               modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 4);
-               modexClearRegion(mv[3].page, 0, 0, 20, 36, 15);
-               //IN_UserInput(1,1);
-       }
-       if(IN_KeyDown(66))      //f8
-       {
-//             modexDrawSprite(mv[0].page, 16, 16, p);
-               modexDrawSprite(mv[0].page, 32+48, 16, (player[0].data));
-       }
-       //TODO fmemtest into page
-       /*if(IN_KeyDown(4+1))   //4
-       {
-               pg=1;
-               SELECT_ALL_PLANES();
-               _fmemset(((mv[pg].page->data+4)+(16*(mv[pg].page->width/4))), 15, 4);
-       }*/
-
-       //9
-       if(IN_KeyDown(10)){ modexPalOverscan(rand()%56); modexPalUpdate1(dpal); IN_UserInput(1,1); }
-       //if(IN_KeyDown(11)){ modexPalOverscan(15); }
-       if((player[0].q==1) && !(player[0].x%TILEWH==0 && player[0].y%TILEWH==0)) break;        //incase things go out of sync!
-       }
-
-       /* fade back to text mode */
-       /* but 1st lets save the game palette~ */
-#ifdef MODEX
-#ifdef FADE
-       modexPalSave(gpal);
-       modexSavePalFile("data/g.pal", gpal);
-       modexFadeOff(4, gpal);
-#endif
-       VGAmodeX(0, 1, &gvar);
-#endif
-       IN_Shutdown();
-       printf("\nProject 16 scroll.exe. This is just a test file!\n");
-       printf("version %s\n", VERSION);
-       printf("tx: %d  ", mv[0].tx);
-       printf("ty: %d\n", mv[0].ty);
-       printf("\n");
-       printf("player vars:\n");
-       printf("        x: %d", player[0].x); printf("  y: %d\n", player[0].y);
-       //if(player[0].hp==0) printf("%d wwww\n", player[0].y+8);
-       //else printf("\nplayer[0].y: %d\n", player[0].y);
-       printf("        tx: %d", player[0].tx); printf("        ty: %d\n", player[0].ty);
-       printf("        triggx: %d", player[0].triggerx); printf("      triggy: %d\n", player[0].triggery);
-       printf("        hp: %d", (player[0].hp));       printf("        q: %d", player[0].q);   printf("        player.info.dir: %d", player[0].info.dir);      printf("        player.d: %d ", player[0].d);
-               printf("        pdir=%d\n", player[0].pdir);
-       printf("        tile data value at player trigger position: %d\n\n", mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))]);
-//     printf("palette offset: %d\n", paloffset/3);
-//++++ printf("Total used: %zu\n", oldfreemem-GetFreeSize());
-//++++ printf("Total free: %zu\n", GetFreeSize());
-//not used now printf("temporary player sprite 0: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=45556867\n");
-//not used now printf("temporary player sprite 1: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=44606385\n");
-       printf("Virtual Screen: %dx", gvar.video.page[0].width);        printf("%d      ", gvar.video.page[0].height);
-       printf("Screen: %dx", gvar.video.page[0].sw);   printf("%d\n", gvar.video.page[0].sh);
-       printf("virtual tile resolution: %dx", gvar.video.page[0].tilesw);      printf("%d      ", gvar.video.page[0].tilesh);
-       printf("tile resolution: %dx", gvar.video.page[0].tw);  printf("%d\n", gvar.video.page[0].th);
-       printf("middle tile position: %dx", gvar.video.page[0].tilemidposscreenx);      printf("%d\n", gvar.video.page[0].tilemidposscreeny);
-       modexprintmeminfo(&gvar.video);
-       //printf("mv[%u].tx: %d", pan.pn, mv[pan.pn].tx); printf("      mv[%u].ty: %d   ", pan.pn, mv[pan.pn].ty);
-       printf("gvar.video.p=%u ", gvar.video.p); printf("gvar.video.r=%u ", gvar.video.r);
-       printf("pageflipflop=%u\n", pageflipflop);
-       //0000printf("\ngvar.video.tickclk=%f\n", gvar.video.tickclk);
-       //0000printf("gvar.video.clk=%f", gvar.video.clk);
-       printf("\n");
-       //printf("map.width=%d  map.height=%d   map.data[0]=%d\n", mv[0].map->width, mv[0].map->height, mv[0].map->data[0]);
-
-       printf("\n");
-       switch(detectcpu())
-       {
-               case 0: cpus = "8086/8088 or 186/88"; break;
-               case 1: cpus = "286"; break;
-               case 2: cpus = "386 or newer"; break;
-               default: cpus = "internal error"; break;
-       }
-       printf("detected CPU type: %s\n", cpus);
-#ifdef MODEX
-#ifdef FADE
-       modexFadeOn(4, dpal);
-#endif
-#endif
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "src/lib/scroll16.h"\r
+#include "src/lib/16_timer.h"\r
+#include "src/lib/wcpu/wcpu.h"\r
+\r
+//#define FADE\r
+#define MODEX  //this is for mode x initiating\r
+\r
+//word far *clock= (word far*) 0x046C; /* 18.2hz clock */\r
+//bitmap_t *p;\r
+global_game_variables_t gvar;\r
+static map_t map;\r
+player_t player[MaxPlayers];\r
+map_view_t mv[4];\r
+//word pn=0; //i forgot ww\r
+float t;\r
+sword bakapee;\r
+pan_t pan;\r
+//debugswitches\r
+boolean panswitch=0;\r
+//extern boolean pageflipflop=1;\r
+       unsigned int i;\r
+       const char *cpus;\r
+       //static int persist_aniframe = 0;    /* gonna be increased to 1 before being used, so 0 is ok for default */\r
+\r
+       //map_view_db_t pgid[4];\r
+       word pg;\r
+//#ifdef FADE\r
+       static word paloffset=0;\r
+       byte *dpal;\r
+//#endif\r
+       byte *gpal;\r
+       byte *ptr;\r
+       byte *mappalptr;\r
+\r
+void main(int argc, char *argv[])\r
+{\r
+       byte *mesg=malloc(sizeof(dword));\r
+\r
+       if(argv[1]) bakapee = atoi(argv[1]);\r
+       else bakapee = 1;\r
+\r
+       // DOSLIB: check our environment\r
+       probe_dos();\r
+\r
+       // DOSLIB: what CPU are we using?\r
+       // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS.\r
+       //      So this code by itself shouldn't care too much what CPU it's running on. Except that other\r
+       //      parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for\r
+       //      the CPU to carry out tasks. --J.C.\r
+       cpu_probe();\r
+\r
+       // DOSLIB: check for VGA\r
+       if (!probe_vga()) {\r
+               printf("VGA probe failed\n");\r
+               return;\r
+       }\r
+       // hardware must be VGA or higher!\r
+       if (!(vga_state.vga_flags & VGA_IS_VGA)) {\r
+               printf("This program requires VGA or higher graphics hardware\n");\r
+               return;\r
+       }\r
+\r
+       if (_DEBUG_INIT() == 0) {\r
+#ifdef DEBUGSERIAL\r
+               printf("WARNING: Failed to initialize DEBUG output\n");\r
+#endif\r
+       }\r
+       _DEBUG("Serial debug output started\n"); // NTS: All serial output must end messages with newline, or DOSBox-X will not emit text to log\r
+       _DEBUGF("Serial debug output printf test %u %u %u\n",1U,2U,3U);\r
+\r
+       pan.pn=1;\r
+\r
+       start_timer(&gvar);\r
+\r
+       /* create the map */\r
+       fprintf(stderr, "testing map load~      ");\r
+       loadmap("data/test.map", &map);\r
+       chkmap(&map, 0);\r
+       printf("chkmap ok       ");\r
+       fprintf(stderr, "yay map loaded~~\n");\r
+\r
+       /* draw the tiles */\r
+#ifdef MODEX\r
+       ptr = map.data;\r
+       //mappalptr = map.tiles->btdata->palette;\r
+\r
+       /* data */\r
+       player[0].data = malloc(48*128); //TODO use exmm\r
+       *player[0].data = bitmapLoadPcx("data/chikyuu.pcx"); // load sprite\r
+\r
+       /* create the planar buffer */\r
+////++++       (player[0].data) = *planar_buf_from_bitmap(&p);\r
+       /*++++printf("load pee!!        ");\r
+       pp = planar_buf_from_bitmap(&p);\r
+       printf("done!\n");*/\r
+\r
+#endif\r
+       /*      input!  */\r
+       IN_Startup();\r
+       IN_Default(0,&player,ctrl_Joystick);\r
+       //IN_Default(1,&player,ctrl_Joystick);\r
+\r
+       /* save the palette */\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       dpal = modexNewPal();\r
+       modexPalSave(dpal);\r
+       modexFadeOff(4, dpal);\r
+#endif\r
+\r
+       textInit();\r
+       VGAmodeX(bakapee, 1, &gvar);\r
+//     printf("%dx%d\n", gvar.video.page[0].sw, gvar.video.page[0].sh);\r
+#ifdef FADE\r
+       modexPalBlack();        //reset the palette~\r
+#endif\r
+#endif\r
+//     printf("Total used @ before palette initiation:         %zu\n", oldfreemem-GetFreeSize());\r
+//++++ player[0].data.offset=(paloffset/3);\r
+//++++ modexPalUpdate1(&player[0].data, &paloffset, 0, 0);\r
+               modexPalUpdate1(player[0].data->palette);\r
+//++++0000             modexPalUpdate1(map.tiles->btdata->palette);\r
+       //printf("      %d\n", sizeof(ptmp->data));\r
+       //printf("1:    %d\n", paloffset);\r
+//++++ map.tiles->data->offset=(paloffset/3);\r
+       //XTmodexPalUpdate(map.tiles->data, &paloffset, 0, 0);\r
+//     printf("\n====\n");\r
+//     printf("0       paloffset=      %d\n", paloffset/3);\r
+//     printf("====\n\n");\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       gpal = modexNewPal();\r
+       modexPalSave(gpal);\r
+       modexSavePalFile("data/g.pal", gpal);\r
+       modexPalBlack();        //so player will not see loadings~\r
+#endif\r
+#endif\r
+\r
+       /* setup camera and screen~ */\r
+       modexHiganbanaPageSetup(&gvar.video);\r
+       for(i=0;i<gvar.video.num_of_pages;i++)\r
+       {\r
+               mv[i].page = &gvar.video.page[i];\r
+               mv[i].map = &map;\r
+               mv[i].video = &gvar.video;\r
+               mv[i].pan       = &pan;\r
+       }\r
+\r
+       /* set up paging */\r
+       //TODO: LOAD map data and position the map in the middle of the screen if smaller then screen\r
+       mapGoTo(mv, 0, 0);\r
+       //_fmemcpy(mv[1].page->data, mv[0].page->data, mv[0].page->pagesize);\r
+\r
+       //TODO: put player in starting position of spot\r
+       //default player position on the viewable map\r
+       player[0].tx = mv[0].tx + mv[0].page->tilemidposscreenx;\r
+       player[0].ty = mv[0].ty + mv[0].page->tilemidposscreeny;\r
+       IN_initplayer(&player, 0);\r
+       //IN_initplayer(&player, 1);\r
+\r
+#ifndef        SPRITE\r
+       modexClearRegion(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);\r
+       //modexClearRegion(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);\r
+#else\r
+       //PBUFSFUN(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 64, 24, 32, PLAYERBMPDATA);\r
+       PBUFSFUN(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 64, 16, 32,   player[0].data);\r
+#endif\r
+\r
+       if(!pageflipflop)       modexShowPage(mv[1].page);\r
+       else                    modexShowPage(mv[0].page);//!(gvar.video.p)\r
+               shinku_fps_indicator_page = 0; // we're on page 1 now, shinku(). follow along please or it will not be visible.\r
+\r
+       /* buffer pages */\r
+//     modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 47);\r
+//     modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 45);\r
+//     {\r
+//             unsigned int k,j,o;\r
+//             /* fill screen with a distinctive pattern */\r
+//             for (k=0;k < vga_state.vga_width;k++) {\r
+//                     o = k >> 2;\r
+//                     vga_write_sequencer(0x02/*map mask*/,1 << (k&3));\r
+//                             for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride)\r
+//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!\r
+//             }\r
+//     }\r
+       modexClearRegion(mv[3].page, 0, 128, 24, 36, 15);\r
+\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       modexFadeOn(4, gpal);\r
+#endif\r
+#endif\r
+       while(!IN_KeyDown(sc_Escape) && player[0].hp>0)\r
+       {\r
+               shinku(&gvar);\r
+       //top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square\r
+       //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction\r
+       //when player[0].tx or player[0].ty == 0 or player[0].tx == 20 or player[0].ty == 15 then stop because that is edge of map and you do not want to walk of the map\r
+\r
+       //player movement\r
+               IN_ReadControl(0,&player);\r
+       if(!panswitch){\r
+               walk(mv, player, 0);\r
+       }else{\r
+               panpagemanual(mv, player, 0);\r
+               //printf("      player[0].q: %d", player[0].q); printf("        player[0].d: %d\n", player[0].d);\r
+       }\r
+\r
+       //the scripting stuff....\r
+       //if(((player[0].triggerx == TRIGGX && player[0].triggery == TRIGGY) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))\r
+       if(((mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))] == 0) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))\r
+       {\r
+               short i;\r
+               for(i=800; i>=400; i--)\r
+               {\r
+                       sound(i);\r
+               }\r
+               nosound();\r
+       }\r
+       if(player[0].q == (TILEWH/(player[0].speed))+1 && player[0].info.dir != 2 && (player[0].triggerx == 5 && player[0].triggery == 5)){ player[0].hp--; }\r
+       //debugging binds!\r
+       if(IN_KeyDown(2)){ modexShowPage(mv[0].page); pan.pn=0; }\r
+       if(IN_KeyDown(3)){ modexShowPage(mv[1].page); pan.pn=1; }\r
+       if(IN_KeyDown(4)){ modexShowPage(mv[2].page); pan.pn=2; }\r
+       if(IN_KeyDown(4+1)){ modexShowPage(mv[3].page); pan.pn=3; }\r
+       if(IN_KeyDown(25)){ modexpdump(mv[0].page); modexpdump(mv[1].page);\r
+                IN_UserInput(1,1);\r
+       }       //p\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       if(IN_KeyDown(24)){ modexPalUpdate0(gpal); paloffset=0; modexpdump(mv[0].page); modexpdump(mv[1].page);  IN_UserInput(1,1); }\r
+       if(IN_KeyDown(22)){\r
+       paloffset=0; modexPalBlack(); modexPalUpdate(player[0].data, &paloffset, 0, 0);\r
+       printf("1paloffset      =       %d\n", paloffset/3);\r
+        modexPalUpdate(map.tiles->data, &paloffset, 0, 0);\r
+       printf("2paloffset      =       %d\n", paloffset/3);\r
+        modexpdump(mv[0].page); modexpdump(mv[1].page);\r
+               IN_UserInput(1,1);\r
+       }\r
+#endif\r
+#endif\r
+       //pan switch\r
+       if(IN_KeyDown(88)){panswitch=!panswitch; IN_UserInput(1,1);}    //f12\r
+       if(IN_KeyDown(87))      //f11\r
+       {\r
+               pageflipflop=!pageflipflop;\r
+               IN_UserInput(1,1);\r
+//             VGAmodeX(0, 0, &gvar);\r
+//             IN_Shutdown();\r
+//             __asm\r
+//             {\r
+//                     mov ah,31h\r
+//                     int 21h\r
+//             }\r
+       }\r
+       if(IN_KeyDown(68))      //f10\r
+       {\r
+               gvar.kurokku.fpscap=!gvar.kurokku.fpscap;\r
+               IN_UserInput(1,1);\r
+       }\r
+       if(IN_KeyDown(67))      //f9\r
+       {\r
+               modexClearRegion(mv[1].page, 0, 0, mv[1].page->width, mv[1].page->height, 2);\r
+               modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 3);\r
+               modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 4);\r
+               modexClearRegion(mv[3].page, 0, 0, 20, 36, 15);\r
+               //IN_UserInput(1,1);\r
+       }\r
+       if(IN_KeyDown(66))      //f8\r
+       {\r
+//             modexDrawSprite(mv[0].page, 16, 16, p);\r
+               modexDrawSprite(mv[0].page, 32+48, 16, (player[0].data));\r
+       }\r
+       //TODO fmemtest into page\r
+       /*if(IN_KeyDown(4+1))   //4\r
+       {\r
+               pg=1;\r
+               SELECT_ALL_PLANES();\r
+               _fmemset(((mv[pg].page->data+4)+(16*(mv[pg].page->width/4))), 15, 4);\r
+       }*/\r
+\r
+       //9\r
+       if(IN_KeyDown(10)){ modexPalOverscan(rand()%56); modexPalUpdate1(dpal); IN_UserInput(1,1); }\r
+       //if(IN_KeyDown(11)){ modexPalOverscan(15); }\r
+       if((player[0].q==1) && !(player[0].x%TILEWH==0 && player[0].y%TILEWH==0)) break;        //incase things go out of sync!\r
+       }\r
+\r
+       /* fade back to text mode */\r
+       /* but 1st lets save the game palette~ */\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       modexPalSave(gpal);\r
+       modexSavePalFile("data/g.pal", gpal);\r
+       modexFadeOff(4, gpal);\r
+#endif\r
+       VGAmodeX(0, 1, &gvar);\r
+#endif\r
+       IN_Shutdown();\r
+       printf("\nProject 16 scroll.exe. This is just a test file!\n");\r
+       printf("version %s\n", VERSION);\r
+       printf("tx: %d  ", mv[0].tx);\r
+       printf("ty: %d\n", mv[0].ty);\r
+       printf("\n");\r
+       printf("player vars:\n");\r
+       printf("        x: %d", player[0].x); printf("  y: %d\n", player[0].y);\r
+       //if(player[0].hp==0) printf("%d wwww\n", player[0].y+8);\r
+       //else printf("\nplayer[0].y: %d\n", player[0].y);\r
+       printf("        tx: %d", player[0].tx); printf("        ty: %d\n", player[0].ty);\r
+       printf("        triggx: %d", player[0].triggerx); printf("      triggy: %d\n", player[0].triggery);\r
+       printf("        hp: %d", (player[0].hp));       printf("        q: %d", player[0].q);   printf("        player.info.dir: %d", player[0].info.dir);      printf("        player.d: %d ", player[0].d);\r
+               printf("        pdir=%d\n", player[0].pdir);\r
+       printf("        tile data value at player trigger position: %d\n\n", mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))]);\r
+//     printf("palette offset: %d\n", paloffset/3);\r
+//++++ printf("Total used: %zu\n", oldfreemem-GetFreeSize());\r
+//++++ printf("Total free: %zu\n", GetFreeSize());\r
+//not used now printf("temporary player sprite 0: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=45556867\n");\r
+//not used now printf("temporary player sprite 1: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=44606385\n");\r
+       printf("Virtual Screen: %dx", gvar.video.page[0].width);        printf("%d      ", gvar.video.page[0].height);\r
+       printf("Screen: %dx", gvar.video.page[0].sw);   printf("%d\n", gvar.video.page[0].sh);\r
+       printf("virtual tile resolution: %dx", gvar.video.page[0].tilesw);      printf("%d      ", gvar.video.page[0].tilesh);\r
+       printf("tile resolution: %dx", gvar.video.page[0].tw);  printf("%d\n", gvar.video.page[0].th);\r
+       printf("middle tile position: %dx", gvar.video.page[0].tilemidposscreenx);      printf("%d\n", gvar.video.page[0].tilemidposscreeny);\r
+       modexprintmeminfo(&gvar.video);\r
+       //printf("mv[%u].tx: %d", pan.pn, mv[pan.pn].tx); printf("      mv[%u].ty: %d   ", pan.pn, mv[pan.pn].ty);\r
+       printf("gvar.video.p=%u ", gvar.video.p); printf("gvar.video.r=%u ", gvar.video.r);\r
+       printf("pageflipflop=%u\n", pageflipflop);\r
+       //0000printf("\ngvar.video.tickclk=%f\n", gvar.video.tickclk);\r
+       //0000printf("gvar.video.clk=%f", gvar.video.clk);\r
+       printf("\n");\r
+       //printf("map.width=%d  map.height=%d   map.data[0]=%d\n", mv[0].map->width, mv[0].map->height, mv[0].map->data[0]);\r
+\r
+       printf("\n");\r
+       switch(detectcpu())\r
+       {\r
+               case 0: cpus = "8086/8088 or 186/88"; break;\r
+               case 1: cpus = "286"; break;\r
+               case 2: cpus = "386 or newer"; break;\r
+               default: cpus = "internal error"; break;\r
+       }\r
+       printf("detected CPU type: %s\n", cpus);\r
+#ifdef MODEX\r
+#ifdef FADE\r
+       modexFadeOn(4, dpal);\r
+#endif\r
+#endif\r
+}\r
index b78f449edcc119a4a352d3316768364d7c7afb37..40a2ac41445f5f8db4840afdd1802e3dc1155c50 100755 (executable)
-/* testemm.c
- *
- * Test program: Expanded Memory Manager functions
- * (C) 2011-2012 Jonathan Campbell.
- * Hackipedia DOS library.
- *
- * This code is licensed under the LGPL.
- * <insert LGPL legal text here>
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <assert.h>
-#include <stdio.h>
-#include <conio.h>
-#include <dos.h>
-
-//#include "src/lib/doslib/cpu.h"
-#include "src/lib/doslib/dos.h"
-#include "src/lib/doslib/emm.h"
-//#include <hw/dos/doswin.h>
-
-static const char *message = "Hello world. How are you?";
-static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja.";
-static char tmp[128],tmp2[128];
-extern int probe_emm0();
-
-#if 1
-# define x_memcpy(a,b,c) memcpy(a,b,c)
-#else
-/* what have we come to when friggin' memcpy() causes a GPF?!? */
-static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) {
-       fprintf(stderr,"memcpy %p -> %p (%lu)\n",
-               dst,src,(unsigned long)c);
-
-       while (c != 0) {
-           *dst++ = *src++;
-           c--;
-       }
-}
-#endif
-
-int main() {
-       size_t message_l = strlen(message),message2_l = strlen(message2);
-
-       probe_dos();
-       printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF);
-       /*if (detect_windows()) {
-               printf("I am running under Windows.\n");
-               printf("    Mode: %s\n",windows_mode_str(windows_mode));
-               printf("    Ver:  %x.%02u\n",windows_version>>8,windows_version&0xFF);
-       }
-       else {
-               printf("Not running under Windows or OS/2\n");
-       }*/
-
-       sanity();
-       if (probe_emm()) {
-               int h1,h2,h3;
-
-               sanity();
-               printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F);
-               emm_update_page_count();
-               sanity();
-               printf("  Unallocated pages:     %u (%luKB)\n",
-                       emm_unallocated_pages,
-                       (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */
-               printf("  Total pages:           %u (%luKB)\n",
-                       emm_total_pages,
-                       (unsigned long)emm_total_pages << 4UL);
-               printf("  Physical pages:        %u (%luKB)\n",
-                       emm_phys_pages,
-                       (unsigned long)emm_phys_pages << 4UL);
-
-               while (getch() != 13);
-               sanity();
-
-               /* print out the mapping table, if available */
-               if (emm_phys_map != NULL) {
-                       struct emm_phys_page_map *me;
-                       unsigned int i;
-
-                       printf("Physical page to segment table\n");
-                       for (i=0;i < emm_phys_pages;i++) {
-                               me = emm_phys_map + i;
-                               printf("  %02x: 0x%04x",me->number,me->segment);
-                               if ((i%5) == 4) printf("\n");
-                       }
-                       printf("\n");
-                       sanity();
-               }
-
-               printf("Allocating EMM pages (1): ");
-               h1 = emm_alloc_pages(1);
-               sanity();
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (!emm_free_pages(h1)) printf("cannot free\n");
-               }
-               else printf("FAILED\n");
-
-               printf("Allocating EMM pages (16KB): ");
-               h1 = emm_alloc_pages(1);
-               sanity();
-               if (h1 >= 0) printf("OK, handle=%u\n",h1);
-               else printf("FAILED\n");
-
-               printf("Allocating EMM pages (1.6MB): ");
-               h2 = emm_alloc_pages(0x19999AUL >> 14UL);
-               sanity();
-               if (h2 >= 0) printf("OK, handle=%u\n",h2);
-               else printf("FAILED\n");
-
-               printf("Allocating EMM pages (12MB): ");
-               h3 = emm_alloc_pages(0xC00000UL >> 14UL);
-               sanity();
-               if (h3 >= 0) printf("OK, handle=%u\n",h3);
-               else printf("FAILED\n");
-
-               while (getch() != 13);
-
-               if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n");
-               sanity();
-               if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n");
-               sanity();
-               if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n");
-               sanity();
-
-               printf("Allocating EMM pages (32KB): ");
-               h1 = emm_alloc_pages(2);
-               sanity();
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (emm_map_page(h1,/*physical*/0,/*logical*/0)) {
-                               unsigned int segm = emm_last_phys_page_segment(0);
-                               printf("Seg %04x\n",segm);
-                               sanity();
-                               if (segm > 0) {
-#if TARGET_MSDOS == 16
-                                       char far *ptr = MK_FP(segm,0);
-#else
-                                       char *ptr = (char*)(segm << 4UL);
-#endif
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy(ptr,(char far*)message,message_l+1);
-                                       _fmemcpy((char far*)tmp,ptr,message_l+1);
-#else
-                                       x_memcpy(ptr,message,message_l+1);
-                                       x_memcpy(tmp,ptr,message_l+1);
-#endif
-                                       printf("After writing message there, I read back: '%s'\n",tmp);
-
-                                       if (!emm_map_page(h1,0,1)) printf("Cannot remap\n");
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy(ptr,(char far*)message2,message2_l+1);
-                                       _fmemcpy((char far*)tmp,ptr,message2_l+1);
-#else
-                                       x_memcpy(ptr,message2,message2_l+1);
-                                       x_memcpy(tmp,ptr,message2_l+1);
-#endif
-                                       printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp);
-
-                                       if (!emm_map_page(h1,0,0)) printf("Cannot remap\n");
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy((char far*)tmp,ptr,message_l+1);
-#else
-                                       x_memcpy(tmp,ptr,message_l+1);
-#endif
-                                       printf("After mapping back to 1, I read back: '%s'\n",tmp);
-
-                                       if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n");
-                               }
-                               else {
-                                       printf("Cannot get segment\n");
-                               }
-                               if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n");
-                       }
-                       else {
-                               printf("Cannot map\n");
-                       }
-                       if (!emm_free_pages(h1)) printf("Cannot free\n");
-               }
-               else printf("FAILED\n");
-
-               printf("Allocating EMM pages (32KB): ");
-               h1 = emm_alloc_pages(2);
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (    emm_map_page(h1,/*physical*/0,/*logical*/0) &&
-                               emm_map_page(h1,/*physical*/1,/*logical*/1)) {
-                               unsigned int seg1 = emm_last_phys_page_segment(0);
-                               unsigned int seg2 = emm_last_phys_page_segment(1);
-                               printf("Seg %04x,%04x\n",seg1,seg2);
-                               if (seg1 > 0 && seg2 > 0) {
-#if TARGET_MSDOS == 16
-                                       char far *ptr1 = MK_FP(seg1,0);
-                                       char far *ptr2 = MK_FP(seg2,0);
-#else
-                                       char *ptr1 = (char*)(seg1 << 4UL);
-                                       char *ptr2 = (char*)(seg2 << 4UL);
-#endif
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy(ptr1,(char far*)message,message_l+1);
-                                       _fmemcpy(ptr2,(char far*)message2,message2_l+1);
-#else
-                                       memcpy(ptr1,message,message_l+1);
-                                       memcpy(ptr2,message2,message2_l+1);
-#endif
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy((char far*)tmp,ptr1,message_l+1);
-                                       _fmemcpy((char far*)tmp2,ptr2,message2_l+1);
-#else
-                                       memcpy(tmp,ptr1,message_l+1);
-                                       memcpy(tmp2,ptr2,message2_l+1);
-#endif
-
-                                       printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2);
-
-                                       /* now swap the pages */
-                                       if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n");
-                                       if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n");
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy((char far*)tmp,ptr1,message2_l+1);
-                                       _fmemcpy((char far*)tmp2,ptr2,message_l+1);
-#else
-                                       memcpy(tmp,ptr1,message2_l+1);
-                                       memcpy(tmp2,ptr2,message_l+1);
-#endif
-
-                                       printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2);
-                               }
-                               else {
-                                       printf("Cannot get segment\n");
-                               }
-                               if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n");
-                       }
-                       else {
-                               printf("Cannot map\n");
-                       }
-                       if (!emm_free_pages(h1)) printf("Cannot free\n");
-               }
-               else printf("FAILED\n");
-
-               getch();
-
-               /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB.
-                * the host could have 256MB of total memory and it would still report 32MB in EMS */
-               printf("we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\n the host could have 256MB of total memory and it would still report 32MB in EMS");
-               printf("Allocating EMM pages (48MB): ");
-               h1 = emm_alloc_pages((48UL << 20UL) >> 14UL);
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (!emm_free_pages(h1)) printf("cannot free\n");
-               }
-               else printf("FAILED\n");
-
-               printf("Allocating EMM pages (96MB): ");
-               h1 = emm_alloc_pages((96UL << 20UL) >> 14UL);
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (!emm_free_pages(h1)) printf("cannot free\n");
-               }
-               else printf("FAILED\n");
-       }
-
-       return 0;
-}
-
+/* testemm.c\r
+ *\r
+ * Test program: Expanded Memory Manager functions\r
+ * (C) 2011-2012 Jonathan Campbell.\r
+ * Hackipedia DOS library.\r
+ *\r
+ * This code is licensed under the LGPL.\r
+ * <insert LGPL legal text here>\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stdint.h>\r
+#include <assert.h>\r
+#include <stdio.h>\r
+#include <conio.h>\r
+#include <dos.h>\r
+\r
+//#include "src/lib/doslib/cpu.h"\r
+#include "src/lib/doslib/dos.h"\r
+#include "src/lib/doslib/emm.h"\r
+//#include <hw/dos/doswin.h>\r
+\r
+static const char *message = "Hello world. How are you?";\r
+static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja.";\r
+static char tmp[128],tmp2[128];\r
+extern int probe_emm0();\r
+\r
+#if 1\r
+# define x_memcpy(a,b,c) memcpy(a,b,c)\r
+#else\r
+/* what have we come to when friggin' memcpy() causes a GPF?!? */\r
+static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) {\r
+       fprintf(stderr,"memcpy %p -> %p (%lu)\n",\r
+               dst,src,(unsigned long)c);\r
+\r
+       while (c != 0) {\r
+           *dst++ = *src++;\r
+           c--;\r
+       }\r
+}\r
+#endif\r
+\r
+int main() {\r
+       size_t message_l = strlen(message),message2_l = strlen(message2);\r
+\r
+       probe_dos();\r
+       printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF);\r
+       /*if (detect_windows()) {\r
+               printf("I am running under Windows.\n");\r
+               printf("    Mode: %s\n",windows_mode_str(windows_mode));\r
+               printf("    Ver:  %x.%02u\n",windows_version>>8,windows_version&0xFF);\r
+       }\r
+       else {\r
+               printf("Not running under Windows or OS/2\n");\r
+       }*/\r
+\r
+       sanity();\r
+       if (probe_emm()) {\r
+               int h1,h2,h3;\r
+\r
+               sanity();\r
+               printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F);\r
+               emm_update_page_count();\r
+               sanity();\r
+               printf("  Unallocated pages:     %u (%luKB)\n",\r
+                       emm_unallocated_pages,\r
+                       (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */\r
+               printf("  Total pages:           %u (%luKB)\n",\r
+                       emm_total_pages,\r
+                       (unsigned long)emm_total_pages << 4UL);\r
+               printf("  Physical pages:        %u (%luKB)\n",\r
+                       emm_phys_pages,\r
+                       (unsigned long)emm_phys_pages << 4UL);\r
+\r
+               while (getch() != 13);\r
+               sanity();\r
+\r
+               /* print out the mapping table, if available */\r
+               if (emm_phys_map != NULL) {\r
+                       struct emm_phys_page_map *me;\r
+                       unsigned int i;\r
+\r
+                       printf("Physical page to segment table\n");\r
+                       for (i=0;i < emm_phys_pages;i++) {\r
+                               me = emm_phys_map + i;\r
+                               printf("  %02x: 0x%04x",me->number,me->segment);\r
+                               if ((i%5) == 4) printf("\n");\r
+                       }\r
+                       printf("\n");\r
+                       sanity();\r
+               }\r
+\r
+               printf("Allocating EMM pages (1): ");\r
+               h1 = emm_alloc_pages(1);\r
+               sanity();\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (!emm_free_pages(h1)) printf("cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+\r
+               printf("Allocating EMM pages (16KB): ");\r
+               h1 = emm_alloc_pages(1);\r
+               sanity();\r
+               if (h1 >= 0) printf("OK, handle=%u\n",h1);\r
+               else printf("FAILED\n");\r
+\r
+               printf("Allocating EMM pages (1.6MB): ");\r
+               h2 = emm_alloc_pages(0x19999AUL >> 14UL);\r
+               sanity();\r
+               if (h2 >= 0) printf("OK, handle=%u\n",h2);\r
+               else printf("FAILED\n");\r
+\r
+               printf("Allocating EMM pages (12MB): ");\r
+               h3 = emm_alloc_pages(0xC00000UL >> 14UL);\r
+               sanity();\r
+               if (h3 >= 0) printf("OK, handle=%u\n",h3);\r
+               else printf("FAILED\n");\r
+\r
+               while (getch() != 13);\r
+\r
+               if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n");\r
+               sanity();\r
+               if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n");\r
+               sanity();\r
+               if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n");\r
+               sanity();\r
+\r
+               printf("Allocating EMM pages (32KB): ");\r
+               h1 = emm_alloc_pages(2);\r
+               sanity();\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (emm_map_page(h1,/*physical*/0,/*logical*/0)) {\r
+                               unsigned int segm = emm_last_phys_page_segment(0);\r
+                               printf("Seg %04x\n",segm);\r
+                               sanity();\r
+                               if (segm > 0) {\r
+#if TARGET_MSDOS == 16\r
+                                       char far *ptr = MK_FP(segm,0);\r
+#else\r
+                                       char *ptr = (char*)(segm << 4UL);\r
+#endif\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy(ptr,(char far*)message,message_l+1);\r
+                                       _fmemcpy((char far*)tmp,ptr,message_l+1);\r
+#else\r
+                                       x_memcpy(ptr,message,message_l+1);\r
+                                       x_memcpy(tmp,ptr,message_l+1);\r
+#endif\r
+                                       printf("After writing message there, I read back: '%s'\n",tmp);\r
+\r
+                                       if (!emm_map_page(h1,0,1)) printf("Cannot remap\n");\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy(ptr,(char far*)message2,message2_l+1);\r
+                                       _fmemcpy((char far*)tmp,ptr,message2_l+1);\r
+#else\r
+                                       x_memcpy(ptr,message2,message2_l+1);\r
+                                       x_memcpy(tmp,ptr,message2_l+1);\r
+#endif\r
+                                       printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp);\r
+\r
+                                       if (!emm_map_page(h1,0,0)) printf("Cannot remap\n");\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy((char far*)tmp,ptr,message_l+1);\r
+#else\r
+                                       x_memcpy(tmp,ptr,message_l+1);\r
+#endif\r
+                                       printf("After mapping back to 1, I read back: '%s'\n",tmp);\r
+\r
+                                       if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n");\r
+                               }\r
+                               else {\r
+                                       printf("Cannot get segment\n");\r
+                               }\r
+                               if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n");\r
+                       }\r
+                       else {\r
+                               printf("Cannot map\n");\r
+                       }\r
+                       if (!emm_free_pages(h1)) printf("Cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+\r
+               printf("Allocating EMM pages (32KB): ");\r
+               h1 = emm_alloc_pages(2);\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (    emm_map_page(h1,/*physical*/0,/*logical*/0) &&\r
+                               emm_map_page(h1,/*physical*/1,/*logical*/1)) {\r
+                               unsigned int seg1 = emm_last_phys_page_segment(0);\r
+                               unsigned int seg2 = emm_last_phys_page_segment(1);\r
+                               printf("Seg %04x,%04x\n",seg1,seg2);\r
+                               if (seg1 > 0 && seg2 > 0) {\r
+#if TARGET_MSDOS == 16\r
+                                       char far *ptr1 = MK_FP(seg1,0);\r
+                                       char far *ptr2 = MK_FP(seg2,0);\r
+#else\r
+                                       char *ptr1 = (char*)(seg1 << 4UL);\r
+                                       char *ptr2 = (char*)(seg2 << 4UL);\r
+#endif\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy(ptr1,(char far*)message,message_l+1);\r
+                                       _fmemcpy(ptr2,(char far*)message2,message2_l+1);\r
+#else\r
+                                       memcpy(ptr1,message,message_l+1);\r
+                                       memcpy(ptr2,message2,message2_l+1);\r
+#endif\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy((char far*)tmp,ptr1,message_l+1);\r
+                                       _fmemcpy((char far*)tmp2,ptr2,message2_l+1);\r
+#else\r
+                                       memcpy(tmp,ptr1,message_l+1);\r
+                                       memcpy(tmp2,ptr2,message2_l+1);\r
+#endif\r
+\r
+                                       printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2);\r
+\r
+                                       /* now swap the pages */\r
+                                       if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n");\r
+                                       if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n");\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy((char far*)tmp,ptr1,message2_l+1);\r
+                                       _fmemcpy((char far*)tmp2,ptr2,message_l+1);\r
+#else\r
+                                       memcpy(tmp,ptr1,message2_l+1);\r
+                                       memcpy(tmp2,ptr2,message_l+1);\r
+#endif\r
+\r
+                                       printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2);\r
+                               }\r
+                               else {\r
+                                       printf("Cannot get segment\n");\r
+                               }\r
+                               if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n");\r
+                       }\r
+                       else {\r
+                               printf("Cannot map\n");\r
+                       }\r
+                       if (!emm_free_pages(h1)) printf("Cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+\r
+               getch();\r
+\r
+               /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\r
+                * the host could have 256MB of total memory and it would still report 32MB in EMS */\r
+               printf("we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\n the host could have 256MB of total memory and it would still report 32MB in EMS");\r
+               printf("Allocating EMM pages (48MB): ");\r
+               h1 = emm_alloc_pages((48UL << 20UL) >> 14UL);\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (!emm_free_pages(h1)) printf("cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+\r
+               printf("Allocating EMM pages (96MB): ");\r
+               h1 = emm_alloc_pages((96UL << 20UL) >> 14UL);\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (!emm_free_pages(h1)) printf("cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
index 16f5654b7cb6de2c2b949a5087b8d25355ff430d..a83564e70a00831b51c28758a223a302617d788c 100755 (executable)
-/* testemm.c
- *
- * Test program: Expanded Memory Manager functions
- * (C) 2011-2012 Jonathan Campbell.
- * Hackipedia DOS library.
- *
- * This code is licensed under the LGPL.
- * <insert LGPL legal text here>
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <assert.h>
-#include <stdio.h>
-#include <conio.h>
-#include <dos.h>
-
-//#include "src/lib/doslib/cpu.h"
-#include "src/lib/doslib/dos.h"
-#include "src/lib/doslib/emm.h"
-//#include <hw/dos/doswin.h>
-
-static const char *message = "Hello world. How are you?";
-static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja.";
-static char tmp[128],tmp2[128];
-extern int probe_emm0();
-
-#if 1
-# define x_memcpy(a,b,c) memcpy(a,b,c)
-#else
-/* what have we come to when friggin' memcpy() causes a GPF?!? */
-static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) {
-       fprintf(stderr,"memcpy %p -> %p (%lu)\n",
-               dst,src,(unsigned long)c);
-
-       while (c != 0) {
-           *dst++ = *src++;
-           c--;
-       }
-}
-#endif
-
-int main() {
-       size_t message_l = strlen(message),message2_l = strlen(message2);
-
-       probe_dos();
-       printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF);
-       /*if (detect_windows()) {
-               printf("I am running under Windows.\n");
-               printf("    Mode: %s\n",windows_mode_str(windows_mode));
-               printf("    Ver:  %x.%02u\n",windows_version>>8,windows_version&0xFF);
-       }
-       else {
-               printf("Not running under Windows or OS/2\n");
-       }*/
-
-       sanity();
-       if (probe_emm()) {
-               int h1,h2,h3;
-
-               sanity();
-               printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F);
-               emm_update_page_count();
-               sanity();
-               printf("  Unallocated pages:     %u (%luKB)\n",
-                       emm_unallocated_pages,
-                       (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */
-               printf("  Total pages:           %u (%luKB)\n",
-                       emm_total_pages,
-                       (unsigned long)emm_total_pages << 4UL);
-               printf("  Physical pages:        %u (%luKB)\n",
-                       emm_phys_pages,
-                       (unsigned long)emm_phys_pages << 4UL);
-
-               while (getch() != 13);
-               sanity();
-
-               /* print out the mapping table, if available */
-               if (emm_phys_map != NULL) {
-                       struct emm_phys_page_map *me;
-                       unsigned int i;
-
-                       printf("Physical page to segment table\n");
-                       for (i=0;i < emm_phys_pages;i++) {
-                               me = emm_phys_map + i;
-                               printf("  %02x: 0x%04x",me->number,me->segment);
-                               if ((i%5) == 4) printf("\n");
-                       }
-                       printf("\n");
-                       sanity();
-               }
-
-               printf("Allocating EMM pages (1): ");
-               h1 = emm_alloc_pages(1);
-               sanity();
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (!emm_free_pages(h1)) printf("cannot free\n");
-               }
-               else printf("FAILED\n");
-
-               printf("Allocating EMM pages (%luKB): ", (dword)emm_unallocated_pages << 4UL);
-               h1 = emm_alloc_pages(emm_unallocated_pages);
-               sanity();
-               if (h1 >= 0) printf("OK, handle=%u\n",h1);
-               else printf("FAILED\n");
-
-//             printf("Allocating EMM pages (1.6MB): ");
-               //h2 = emm_alloc_pages(0x19999AUL >> 14UL);
-               /*h2 = emm_alloc_pages(1);
-               sanity();
-               if (h2 >= 0) printf("OK, handle=%u\n",h2);
-               else printf("FAILED\n");
-
-               //printf("Allocating EMM pages (12MB): ");
-               //h3 = emm_alloc_pages(0xC00000UL >> 14UL);
-               h3 = emm_alloc_pages(1);
-               sanity();
-               if (h3 >= 0) printf("OK, handle=%u\n",h3);
-               else printf("FAILED\n");*/
-
-               while (getch() != 13);
-
-               if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n");
-               sanity();
-               /*if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n");
-               sanity();
-               if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n");
-               sanity();*/
-
-               printf("Allocating EMM pages (32KB): ");
-               h1 = emm_alloc_pages(2);
-               sanity();
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (emm_map_page(h1,/*physical*/0,/*logical*/0)) {
-                               unsigned int segm = emm_last_phys_page_segment(0);
-                               printf("Seg %04x\n",segm);
-                               sanity();
-                               if (segm > 0) {
-#if TARGET_MSDOS == 16
-                                       char far *ptr = MK_FP(segm,0);
-#else
-                                       char *ptr = (char*)(segm << 4UL);
-#endif
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy(ptr,(char far*)message,message_l+1);
-                                       _fmemcpy((char far*)tmp,ptr,message_l+1);
-#else
-                                       x_memcpy(ptr,message,message_l+1);
-                                       x_memcpy(tmp,ptr,message_l+1);
-#endif
-                                       printf("After writing message there, I read back: '%s'\n",tmp);
-
-                                       if (!emm_map_page(h1,0,1)) printf("Cannot remap\n");
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy(ptr,(char far*)message2,message2_l+1);
-                                       _fmemcpy((char far*)tmp,ptr,message2_l+1);
-#else
-                                       x_memcpy(ptr,message2,message2_l+1);
-                                       x_memcpy(tmp,ptr,message2_l+1);
-#endif
-                                       printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp);
-
-                                       if (!emm_map_page(h1,0,0)) printf("Cannot remap\n");
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy((char far*)tmp,ptr,message_l+1);
-#else
-                                       x_memcpy(tmp,ptr,message_l+1);
-#endif
-                                       printf("After mapping back to 1, I read back: '%s'\n",tmp);
-
-                                       if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n");
-                               }
-                               else {
-                                       printf("Cannot get segment\n");
-                               }
-                               if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n");
-                       }
-                       else {
-                               printf("Cannot map\n");
-                       }
-                       if (!emm_free_pages(h1)) printf("Cannot free\n");
-               }
-               else printf("FAILED\n");
-
-               printf("Allocating EMM pages (32KB): ");
-               h1 = emm_alloc_pages(2);
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (    emm_map_page(h1,/*physical*/0,/*logical*/0) &&
-                               emm_map_page(h1,/*physical*/1,/*logical*/1)) {
-                               unsigned int seg1 = emm_last_phys_page_segment(0);
-                               unsigned int seg2 = emm_last_phys_page_segment(1);
-                               printf("Seg %04x,%04x\n",seg1,seg2);
-                               if (seg1 > 0 && seg2 > 0) {
-#if TARGET_MSDOS == 16
-                                       char far *ptr1 = MK_FP(seg1,0);
-                                       char far *ptr2 = MK_FP(seg2,0);
-#else
-                                       char *ptr1 = (char*)(seg1 << 4UL);
-                                       char *ptr2 = (char*)(seg2 << 4UL);
-#endif
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy(ptr1,(char far*)message,message_l+1);
-                                       _fmemcpy(ptr2,(char far*)message2,message2_l+1);
-#else
-                                       memcpy(ptr1,message,message_l+1);
-                                       memcpy(ptr2,message2,message2_l+1);
-#endif
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy((char far*)tmp,ptr1,message_l+1);
-                                       _fmemcpy((char far*)tmp2,ptr2,message2_l+1);
-#else
-                                       memcpy(tmp,ptr1,message_l+1);
-                                       memcpy(tmp2,ptr2,message2_l+1);
-#endif
-
-                                       printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2);
-
-                                       /* now swap the pages */
-                                       if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n");
-                                       if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n");
-
-#if TARGET_MSDOS == 16
-                                       _fmemcpy((char far*)tmp,ptr1,message2_l+1);
-                                       _fmemcpy((char far*)tmp2,ptr2,message_l+1);
-#else
-                                       memcpy(tmp,ptr1,message2_l+1);
-                                       memcpy(tmp2,ptr2,message_l+1);
-#endif
-
-                                       printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2);
-                               }
-                               else {
-                                       printf("Cannot get segment\n");
-                               }
-                               if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n");
-                       }
-                       else {
-                               printf("Cannot map\n");
-                       }
-                       if (!emm_free_pages(h1)) printf("Cannot free\n");
-               }
-               else printf("FAILED\n");
-
-               getch();
-
-               /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB.
-                * the host could have 256MB of total memory and it would still report 32MB in EMS */
-               printf("we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\n the host could have 256MB of total memory and it would still report 32MB in EMS");
-               printf("Allocating EMM pages (48MB): ");
-               h1 = emm_alloc_pages((48UL << 20UL) >> 14UL);
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (!emm_free_pages(h1)) printf("cannot free\n");
-               }
-               else printf("FAILED\n");
-
-               printf("Allocating EMM pages (96MB): ");
-               h1 = emm_alloc_pages((96UL << 20UL) >> 14UL);
-               if (h1 >= 0) {
-                       printf("OK, handle=%u\n",h1);
-                       if (!emm_free_pages(h1)) printf("cannot free\n");
-               }
-               else printf("FAILED\n");
-       }
-
-       return 0;
-}
+/* testemm.c\r
+ *\r
+ * Test program: Expanded Memory Manager functions\r
+ * (C) 2011-2012 Jonathan Campbell.\r
+ * Hackipedia DOS library.\r
+ *\r
+ * This code is licensed under the LGPL.\r
+ * <insert LGPL legal text here>\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stdint.h>\r
+#include <assert.h>\r
+#include <stdio.h>\r
+#include <conio.h>\r
+#include <dos.h>\r
+\r
+//#include "src/lib/doslib/cpu.h"\r
+#include "src/lib/doslib/dos.h"\r
+#include "src/lib/doslib/emm.h"\r
+//#include <hw/dos/doswin.h>\r
+\r
+static const char *message = "Hello world. How are you?";\r
+static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja.";\r
+static char tmp[128],tmp2[128];\r
+extern int probe_emm0();\r
+\r
+#if 1\r
+# define x_memcpy(a,b,c) memcpy(a,b,c)\r
+#else\r
+/* what have we come to when friggin' memcpy() causes a GPF?!? */\r
+static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) {\r
+       fprintf(stderr,"memcpy %p -> %p (%lu)\n",\r
+               dst,src,(unsigned long)c);\r
+\r
+       while (c != 0) {\r
+           *dst++ = *src++;\r
+           c--;\r
+       }\r
+}\r
+#endif\r
+\r
+int main() {\r
+       size_t message_l = strlen(message),message2_l = strlen(message2);\r
+\r
+       probe_dos();\r
+       printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF);\r
+       /*if (detect_windows()) {\r
+               printf("I am running under Windows.\n");\r
+               printf("    Mode: %s\n",windows_mode_str(windows_mode));\r
+               printf("    Ver:  %x.%02u\n",windows_version>>8,windows_version&0xFF);\r
+       }\r
+       else {\r
+               printf("Not running under Windows or OS/2\n");\r
+       }*/\r
+\r
+       sanity();\r
+       if (probe_emm()) {\r
+               int h1,h2,h3;\r
+\r
+               sanity();\r
+               printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F);\r
+               emm_update_page_count();\r
+               sanity();\r
+               printf("  Unallocated pages:     %u (%luKB)\n",\r
+                       emm_unallocated_pages,\r
+                       (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */\r
+               printf("  Total pages:           %u (%luKB)\n",\r
+                       emm_total_pages,\r
+                       (unsigned long)emm_total_pages << 4UL);\r
+               printf("  Physical pages:        %u (%luKB)\n",\r
+                       emm_phys_pages,\r
+                       (unsigned long)emm_phys_pages << 4UL);\r
+\r
+               while (getch() != 13);\r
+               sanity();\r
+\r
+               /* print out the mapping table, if available */\r
+               if (emm_phys_map != NULL) {\r
+                       struct emm_phys_page_map *me;\r
+                       unsigned int i;\r
+\r
+                       printf("Physical page to segment table\n");\r
+                       for (i=0;i < emm_phys_pages;i++) {\r
+                               me = emm_phys_map + i;\r
+                               printf("  %02x: 0x%04x",me->number,me->segment);\r
+                               if ((i%5) == 4) printf("\n");\r
+                       }\r
+                       printf("\n");\r
+                       sanity();\r
+               }\r
+\r
+               printf("Allocating EMM pages (1): ");\r
+               h1 = emm_alloc_pages(1);\r
+               sanity();\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (!emm_free_pages(h1)) printf("cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+\r
+               printf("Allocating EMM pages (%luKB): ", (dword)emm_unallocated_pages << 4UL);\r
+               h1 = emm_alloc_pages(emm_unallocated_pages);\r
+               sanity();\r
+               if (h1 >= 0) printf("OK, handle=%u\n",h1);\r
+               else printf("FAILED\n");\r
+\r
+//             printf("Allocating EMM pages (1.6MB): ");\r
+               //h2 = emm_alloc_pages(0x19999AUL >> 14UL);\r
+               /*h2 = emm_alloc_pages(1);\r
+               sanity();\r
+               if (h2 >= 0) printf("OK, handle=%u\n",h2);\r
+               else printf("FAILED\n");\r
+\r
+               //printf("Allocating EMM pages (12MB): ");\r
+               //h3 = emm_alloc_pages(0xC00000UL >> 14UL);\r
+               h3 = emm_alloc_pages(1);\r
+               sanity();\r
+               if (h3 >= 0) printf("OK, handle=%u\n",h3);\r
+               else printf("FAILED\n");*/\r
+\r
+               while (getch() != 13);\r
+\r
+               if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n");\r
+               sanity();\r
+               /*if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n");\r
+               sanity();\r
+               if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n");\r
+               sanity();*/\r
+\r
+               printf("Allocating EMM pages (32KB): ");\r
+               h1 = emm_alloc_pages(2);\r
+               sanity();\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (emm_map_page(h1,/*physical*/0,/*logical*/0)) {\r
+                               unsigned int segm = emm_last_phys_page_segment(0);\r
+                               printf("Seg %04x\n",segm);\r
+                               sanity();\r
+                               if (segm > 0) {\r
+#if TARGET_MSDOS == 16\r
+                                       char far *ptr = MK_FP(segm,0);\r
+#else\r
+                                       char *ptr = (char*)(segm << 4UL);\r
+#endif\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy(ptr,(char far*)message,message_l+1);\r
+                                       _fmemcpy((char far*)tmp,ptr,message_l+1);\r
+#else\r
+                                       x_memcpy(ptr,message,message_l+1);\r
+                                       x_memcpy(tmp,ptr,message_l+1);\r
+#endif\r
+                                       printf("After writing message there, I read back: '%s'\n",tmp);\r
+\r
+                                       if (!emm_map_page(h1,0,1)) printf("Cannot remap\n");\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy(ptr,(char far*)message2,message2_l+1);\r
+                                       _fmemcpy((char far*)tmp,ptr,message2_l+1);\r
+#else\r
+                                       x_memcpy(ptr,message2,message2_l+1);\r
+                                       x_memcpy(tmp,ptr,message2_l+1);\r
+#endif\r
+                                       printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp);\r
+\r
+                                       if (!emm_map_page(h1,0,0)) printf("Cannot remap\n");\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy((char far*)tmp,ptr,message_l+1);\r
+#else\r
+                                       x_memcpy(tmp,ptr,message_l+1);\r
+#endif\r
+                                       printf("After mapping back to 1, I read back: '%s'\n",tmp);\r
+\r
+                                       if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n");\r
+                               }\r
+                               else {\r
+                                       printf("Cannot get segment\n");\r
+                               }\r
+                               if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n");\r
+                       }\r
+                       else {\r
+                               printf("Cannot map\n");\r
+                       }\r
+                       if (!emm_free_pages(h1)) printf("Cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+\r
+               printf("Allocating EMM pages (32KB): ");\r
+               h1 = emm_alloc_pages(2);\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (    emm_map_page(h1,/*physical*/0,/*logical*/0) &&\r
+                               emm_map_page(h1,/*physical*/1,/*logical*/1)) {\r
+                               unsigned int seg1 = emm_last_phys_page_segment(0);\r
+                               unsigned int seg2 = emm_last_phys_page_segment(1);\r
+                               printf("Seg %04x,%04x\n",seg1,seg2);\r
+                               if (seg1 > 0 && seg2 > 0) {\r
+#if TARGET_MSDOS == 16\r
+                                       char far *ptr1 = MK_FP(seg1,0);\r
+                                       char far *ptr2 = MK_FP(seg2,0);\r
+#else\r
+                                       char *ptr1 = (char*)(seg1 << 4UL);\r
+                                       char *ptr2 = (char*)(seg2 << 4UL);\r
+#endif\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy(ptr1,(char far*)message,message_l+1);\r
+                                       _fmemcpy(ptr2,(char far*)message2,message2_l+1);\r
+#else\r
+                                       memcpy(ptr1,message,message_l+1);\r
+                                       memcpy(ptr2,message2,message2_l+1);\r
+#endif\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy((char far*)tmp,ptr1,message_l+1);\r
+                                       _fmemcpy((char far*)tmp2,ptr2,message2_l+1);\r
+#else\r
+                                       memcpy(tmp,ptr1,message_l+1);\r
+                                       memcpy(tmp2,ptr2,message2_l+1);\r
+#endif\r
+\r
+                                       printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2);\r
+\r
+                                       /* now swap the pages */\r
+                                       if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n");\r
+                                       if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n");\r
+\r
+#if TARGET_MSDOS == 16\r
+                                       _fmemcpy((char far*)tmp,ptr1,message2_l+1);\r
+                                       _fmemcpy((char far*)tmp2,ptr2,message_l+1);\r
+#else\r
+                                       memcpy(tmp,ptr1,message2_l+1);\r
+                                       memcpy(tmp2,ptr2,message_l+1);\r
+#endif\r
+\r
+                                       printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2);\r
+                               }\r
+                               else {\r
+                                       printf("Cannot get segment\n");\r
+                               }\r
+                               if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n");\r
+                       }\r
+                       else {\r
+                               printf("Cannot map\n");\r
+                       }\r
+                       if (!emm_free_pages(h1)) printf("Cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+\r
+               getch();\r
+\r
+               /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\r
+                * the host could have 256MB of total memory and it would still report 32MB in EMS */\r
+               printf("we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\n the host could have 256MB of total memory and it would still report 32MB in EMS");\r
+               printf("Allocating EMM pages (48MB): ");\r
+               h1 = emm_alloc_pages((48UL << 20UL) >> 14UL);\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (!emm_free_pages(h1)) printf("cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+\r
+               printf("Allocating EMM pages (96MB): ");\r
+               h1 = emm_alloc_pages((96UL << 20UL) >> 14UL);\r
+               if (h1 >= 0) {\r
+                       printf("OK, handle=%u\n",h1);\r
+                       if (!emm_free_pages(h1)) printf("cannot free\n");\r
+               }\r
+               else printf("FAILED\n");\r
+       }\r
+\r
+       return 0;\r
+}\r
index 4c5f653443c850642b1126eeab71f374cec9a0bb..43dae78ed1651de061d6c3b181bf58462abf76a0 100755 (executable)
-/* test.c
- *
- * Adlib OPL2/OPL3 FM synthesizer chipset test program.
- * (C) 2010-2012 Jonathan Campbell.
- * Hackipedia DOS library.
- *
- * This code is licensed under the LGPL.
- * <insert LGPL legal text here>
- *
- * Compiles for intended target environments:
- *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]
- *
- * This test program uses a "text user interface" to allow you to play
- * with the OPL2/OPL3 chipset and it's parameters. Some "instruments"
- * are preset for you if you want to make noise faster.
- */
-#include <stdio.h>
-#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <dos.h>
-
-#include <hw/vga/vga.h>
-#include <hw/dos/dos.h>
-#include <hw/8254/8254.h>              /* 8254 timer */
-#include <hw/vga/vgagui.h>
-#include <hw/vga/vgatty.h>
-#include <hw/adlib/adlib.h>
-
-static unsigned int musical_scale[18] = {
-       0x1B0,                  /* E */
-       0x1CA,                  /* F */
-       0x1E5,                  /* f# */
-       0x202,                  /* G */
-       0x220,                  /* G# */
-       0x241,                  /* A */
-       0x263,                  /* A# */
-       0x287,                  /* B */
-       0x2AE,                  /* C */
-
-       0x2B0,                  /* E */
-       0x2CA,                  /* F */
-       0x2E5,                  /* f# */
-       0x302,                  /* G */
-       0x320,                  /* G# */
-       0x341,                  /* A */
-       0x363,                  /* A# */
-       0x387,                  /* B */
-       0x3AE,                  /* C */
-};
-
-int main(int argc,char **argv) {
-       int i,loop,redraw,c,cc,selector=0,redrawln=0,hselect=0,selectsub=0;
-       VGA_ALPHA_PTR vga;
-       char tmp[128];
-
-       printf("ADLIB FM test program\n");
-
-       if (!probe_vga()) {
-               printf("Cannot init VGA\n");
-               return 1;
-       }
-       if (!init_adlib()) {
-               printf("Cannot init library\n");
-               return 1;
-       }
-
-       int10_setmode(3);
-
-       /* for VGA: free up space if needed by going to 80x50 */
-       if (adlib_fm_voices > 9)
-               vga_bios_set_80x50_text();
-
-       memset(adlib_fm,0,sizeof(adlib_fm));
-       memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));
-       for (i=0;i < adlib_fm_voices;i++) {
-               struct adlib_fm_operator *f;
-               f = &adlib_fm[i].mod;
-               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
-               f = &adlib_fm[i].car;
-               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;
-       }
-
-       for (i=0;i < adlib_fm_voices;i++) {
-               struct adlib_fm_operator *f;
-
-               f = &adlib_fm[i].mod;
-               f->mod_multiple = 1;
-               f->total_level = 63 - 16;
-               f->attack_rate = 15;
-               f->decay_rate = 0;
-               f->sustain_level = 7;
-               f->release_rate = 7;
-               f->f_number = musical_scale[i%18];
-               f->octave = 4;
-               f->key_on = 0;
-
-               f = &adlib_fm[i].car;
-               f->mod_multiple = 1;
-               f->total_level = 63 - 16;
-               f->attack_rate = 15;
-               f->decay_rate = 0;
-               f->sustain_level = 7;
-               f->release_rate = 7;
-               f->f_number = 0;
-               f->octave = 0;
-               f->key_on = 0;
-       }
-
-       adlib_apply_all();
-
-       vga_write_color(0x07);
-       vga_clear();
-
-       loop=1;
-       redraw=1;
-       while (loop) {
-               if (redraw || redrawln) {
-                       if (redraw) {
-                               for (vga=vga_alpha_ram,cc=0;cc < (80*vga_height);cc++) *vga++ = 0x1E00 | 177;
-                               vga_moveto(0,0);
-                               vga_write_color(0x1F);
-                               sprintf(tmp,"Adlib FM, %u-voice %s. Use Z & X to adj  F10=PRESET F1=QUIET ",adlib_fm_voices,
-                                       (adlib_flags & ADLIB_FM_OPL3) ? "OPL3" :
-                                       (adlib_flags & ADLIB_FM_DUAL_OPL2) ? "Dual OPL2" : "OPL2");
-                               vga_write(tmp);
-                               if (adlib_flags & ADLIB_FM_OPL3) vga_write("F2=OPL3 off ");
-                       }
-
-                       if (redrawln || redraw) {
-                               struct adlib_reg_bd *bd = &adlib_reg_bd;
-                               static const char *hsel_str[18] = {
-                                       "Amplitude modulatation",
-                                       "Vibrato",
-                                       "Sustain",
-                                       "Key scaling rate",
-                                       "Modulator frequency multiple",
-                                       "Level key scaling",
-                                       "Total level",
-                                       "Attack rate",
-                                       "Decay rate",
-                                       "Sustain level",
-                                       "Release rate",
-                                       "KEY ON",
-                                       "Octave",
-                                       "F-Number",
-                                       "Feedback",
-                                       "Connection (operator 1 -> operator 2)",
-                                       "Waveform",
-                                       "Channel mapping (OPL3)"
-                               };
-
-                               vga_write_color(0x1A);
-
-                               vga_moveto(0,2);
-                               sprintf(tmp,"AM=%u VB=%u RYTHM=%u BAS=%u SNA=%u TOM=%u CYM=%u HI=%u\n",
-                                       bd->am_depth,
-                                       bd->vibrato_depth,
-                                       bd->rythm_enable,
-                                       bd->bass_drum_on,
-                                       bd->snare_drum_on,
-                                       bd->tom_tom_on,
-                                       bd->cymbal_on,
-                                       bd->hi_hat_on);
-                               vga_write(tmp);
-
-                               vga_moveto(0,3);
-                               vga_write("                                                       ");
-                               vga_moveto(0,3);
-                               vga_write(hsel_str[hselect]);
-
-                               vga_moveto(0,4);
-                               vga_write_color(hselect ==  0 ? 0x70 : 0x1E);           vga_write("AM ");
-                               vga_write_color(hselect ==  1 ? 0x70 : 0x1E);           vga_write("VB ");
-                               vga_write_color(hselect ==  2 ? 0x70 : 0x1E);           vga_write("SUST ");
-                               vga_write_color(hselect ==  3 ? 0x70 : 0x1E);           vga_write("KSR ");
-                               vga_write_color(hselect ==  4 ? 0x70 : 0x1E);           vga_write("MMUL ");
-                               vga_write_color(hselect ==  5 ? 0x70 : 0x1E);           vga_write("LKS ");
-                               vga_write_color(hselect ==  6 ? 0x70 : 0x1E);           vga_write("TL ");
-                               vga_write_color(hselect ==  7 ? 0x70 : 0x1E);           vga_write("AR ");
-                               vga_write_color(hselect ==  8 ? 0x70 : 0x1E);           vga_write("DR ");
-                               vga_write_color(hselect ==  9 ? 0x70 : 0x1E);           vga_write("SL ");
-                               vga_write_color(hselect == 10 ? 0x70 : 0x1E);           vga_write("RR ");
-                               vga_write_color(hselect == 11 ? 0x70 : 0x1E);           vga_write("KEY ");
-                               vga_write_color(hselect == 12 ? 0x70 : 0x1E);           vga_write("OCT ");
-                               vga_write_color(hselect == 13 ? 0x70 : 0x1E);           vga_write("FNUM ");
-                               vga_write_color(hselect == 14 ? 0x70 : 0x1E);           vga_write("FEED ");
-                               vga_write_color(hselect == 15 ? 0x70 : 0x1E);           vga_write("CON ");
-                               vga_write_color(hselect == 16 ? 0x70 : 0x1E);           vga_write("WV ");
-                               vga_write_color(hselect == 17 ? 0x70 : 0x1E);           vga_write("ABCD ");
-
-                               for (i=0;i < adlib_fm_voices;i++) {
-                                       struct adlib_fm_operator *f;
-                                       double freq;
-                                       
-                                       f = &adlib_fm[i].mod;
-                                       vga_moveto(0,5+i*2);
-                                       freq = adlib_fm_op_to_freq(f);
-                                       vga_write_color(i == selector && selectsub == 0 ? 0x70 : 0x1E);
-                                       cc = sprintf(tmp,"%u  %u  %u    %u   %-2u   %u   %-2u %-2u %-2u %-2u %-2u %u   %u   %-4u %u    %u   %u  %c%c%c%c %u %.1fHz ",
-                                               f->am,                  f->vibrato,             f->sustain,             f->key_scaling_rate,
-                                               f->mod_multiple,        f->level_key_scale,     f->total_level,         f->attack_rate,
-                                               f->decay_rate,          f->sustain_level,       f->release_rate,        f->key_on,
-                                               f->octave,              f->f_number,            f->feedback,            f->connection,
-                                               f->waveform,            f->ch_a?'*':'-',        f->ch_b?'*':'-',        f->ch_c?'*':'-',
-                                               f->ch_d?'*':'-',        i+1,                    freq);
-                                       vga_write(tmp);
-
-                                       f = &adlib_fm[i].car;
-                                       vga_moveto(0,5+i*2+1);
-                                       vga_write_color(i == selector && selectsub == 1 ? 0x70 : 0x1E);
-                                       cc = sprintf(tmp,"%u  %u  %u    %u   %-2u   %u   %-2u %-2u %-2u %-2u %-2u                       %u       CAR   ",
-                                               f->am,                  f->vibrato,             f->sustain,             f->key_scaling_rate,
-                                               f->mod_multiple,        f->level_key_scale,     f->total_level,         f->attack_rate,
-                                               f->decay_rate,          f->sustain_level,       f->release_rate,        f->waveform);
-                                       vga_write(tmp);
-                               }
-                       }
-
-                       redrawln = 0;
-                       redraw = 0;
-               }
-
-               if (kbhit()) {
-                       c = getch();
-                       if (c == 0) c = getch() << 8;
-
-                       if (c == 27) {
-                               loop = 0;
-                       }
-                       else if (c == 0x3B00) { /* F1 */
-                               for (i=0;i < adlib_fm_voices;i++) {
-                                       adlib_fm[i].mod.key_on = 0;
-                                       adlib_fm[i].car.key_on = 0;
-                                       adlib_update_groupA0(i,&adlib_fm[i]);
-                               }
-                               redrawln = 1;
-                       }
-                       else if (c == 0x3C00) { /* F2 */
-                               if (adlib_flags & ADLIB_FM_OPL3) {
-                                       shutdown_adlib_opl3();
-                                       int10_setmode(3);
-                                       redraw = 1;
-                               }
-                       }
-                       else if (c == 0x4400) { /* F10 */
-                               unsigned short op = adlib_voice_to_op[selector];
-
-                               vga_write_color(0x07);
-                               vga_clear();
-                               vga_moveto(0,0);
-
-                               vga_write("Choose an instrument to load into the channel:\n");
-                               vga_write(" 1. Violin     2. Piano     3. Harpsichord     4. Horn      5. Deep bass drum\n");
-                               vga_write(" 6. Small drum \n");
-                               vga_write_sync();
-
-                               c = getch();
-
-                               if (c == '1')
-                                       adlib_fm[selector] =
-                                               (adlib_flags & ADLIB_FM_OPL3 ?
-                                                adlib_fm_preset_violin_opl3 : adlib_fm_preset_violin_opl2);
-                               else if (c == '2')
-                                       adlib_fm[selector] = adlib_fm_preset_piano;
-                               else if (c == '3')
-                                       adlib_fm[selector] = adlib_fm_preset_harpsichord;
-                               else if (c == '4')
-                                       adlib_fm[selector] = adlib_fm_preset_horn;
-                               else if (c == '5')
-                                       adlib_fm[selector] = adlib_fm_preset_deep_bass_drum;
-                               else if (c == '6')
-                                       adlib_fm[selector] = adlib_fm_preset_small_drum;
-
-                               adlib_update_groupA0(selector,&adlib_fm[selector]);
-                               adlib_update_groupC0(selector,&adlib_fm[selector]);
-                               adlib_update_operator(op,&adlib_fm[selector].mod);
-                               adlib_update_operator(op+3,&adlib_fm[selector].car);
-
-                               redraw = 1;
-                       }
-                       else if (c == ' ') {
-                               adlib_fm[selector].mod.key_on ^= 1;
-                               adlib_update_groupA0(selector,&adlib_fm[selector]);
-                               redrawln=1;
-                       }
-                       else if (c == 'a') {
-                               if (hselect == 17) {
-                                       struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_a ^= 1;
-                                       adlib_update_groupC0(selector,&adlib_fm[selector]);
-                               }
-                               else {
-                                       adlib_reg_bd.am_depth ^= 1;
-                                       adlib_update_bd(&adlib_reg_bd);
-                               }
-                               redrawln = 1;
-                       }
-                       else if (c == 'v') {
-                               adlib_reg_bd.vibrato_depth ^= 1;
-                               adlib_update_bd(&adlib_reg_bd);
-                               redrawln = 1;
-                       }
-                       else if (c == 'r') {
-                               adlib_reg_bd.rythm_enable ^= 1;
-                               adlib_update_bd(&adlib_reg_bd);
-                               redrawln = 1;
-                       }
-                       else if (c == 'b') {
-                               if (hselect == 17) {
-                                       struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_b ^= 1;
-                                       adlib_update_groupC0(selector,&adlib_fm[selector]);
-                               }
-                               else {
-                                       adlib_reg_bd.bass_drum_on ^= 1;
-                                       adlib_update_bd(&adlib_reg_bd);
-                               }
-                               redrawln = 1;
-                       }
-                       else if (c == 's') {
-                               adlib_reg_bd.snare_drum_on ^= 1;
-                               adlib_update_bd(&adlib_reg_bd);
-                               redrawln = 1;
-                       }
-                       else if (c == 't') {
-                               adlib_reg_bd.tom_tom_on ^= 1;
-                               adlib_update_bd(&adlib_reg_bd);
-                               redrawln = 1;
-                       }
-                       else if (c == 'c') {
-                               if (hselect == 17) {
-                                       struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_c ^= 1;
-                                       adlib_update_groupC0(selector,&adlib_fm[selector]);
-                               }
-                               else {
-                                       adlib_reg_bd.cymbal_on ^= 1;
-                                       adlib_update_bd(&adlib_reg_bd);
-                               }
-                               redrawln = 1;
-                       }
-                       else if (c == 'd') {
-                               if (hselect == 17) {
-                                       struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_d ^= 1;
-                                       adlib_update_groupC0(selector,&adlib_fm[selector]);
-                               }
-                               else {
-                               }
-                               redrawln = 1;
-                       }
-                       else if (c == 'h') {
-                               adlib_reg_bd.hi_hat_on ^= 1;
-                               adlib_update_bd(&adlib_reg_bd);
-                               redrawln = 1;
-                       }
-                       else if (c == 'z' || c == 'Z' || c == 'x' || c == 'X') {
-                               struct adlib_fm_operator *f;
-                               int dec = tolower(c) == 'z';
-                               unsigned short operator;
-
-                               switch (hselect) {
-                                       case 11:selectsub = 0;
-                                               break;
-                               }
-
-                               if (selectsub) f = &adlib_fm[selector].car;
-                               else           f = &adlib_fm[selector].mod;
-                               operator = adlib_voice_to_op[selector] + (selectsub*3);
-
-                               switch (hselect) {
-                                       case 0:         f->am ^= 1;                     adlib_update_group20(operator,f); break;
-                                       case 11:        f->key_on ^= 1;                 adlib_update_groupA0(selector,&adlib_fm[selector]); break;
-                                       case 1:         f->vibrato ^= 1;                adlib_update_group20(operator,f); break;
-                                       case 2:         f->sustain ^= 1;                adlib_update_group20(operator,f); break;
-                                       case 15:        f->connection ^= 1;             adlib_update_group20(operator,f); break;
-                                       case 3:         f->key_scaling_rate ^= 1;       adlib_update_group20(operator,f); break;
-
-                                       case 4:         if (dec) f->mod_multiple--; else f->mod_multiple++;
-                                                       adlib_update_group20(operator,f); break;
-                                       case 5:         if (dec) f->level_key_scale--; else f->level_key_scale++;
-                                                       adlib_update_group40(operator,f); break;
-                                       case 6:         if (dec) f->total_level--; else f->total_level++;
-                                                       adlib_update_group40(operator,f); break;
-                                       case 7:         if (dec) f->attack_rate--; else f->attack_rate++;
-                                                       adlib_update_group60(operator,f); break;
-                                       case 8:         if (dec) f->decay_rate--; else f->decay_rate++;
-                                                       adlib_update_group60(operator,f); break;
-                                       case 9:         if (dec) f->sustain_level--; else f->sustain_level++;
-                                                       adlib_update_group80(operator,f); break;
-                                       case 10:        if (dec) f->release_rate--; else f->release_rate++;
-                                                       adlib_update_group80(operator,f); break;
-                                       case 12:        if (dec) f->octave--; else f->octave++;
-                                                       adlib_update_groupA0(selector,&adlib_fm[selector]); break;
-                                       case 13:        if (dec) f->f_number--; else f->f_number++;
-                                                       adlib_update_groupA0(selector,&adlib_fm[selector]); break;
-                                       case 14:        if (dec) f->feedback--; else f->feedback++;
-                                                       adlib_update_groupC0(selector,&adlib_fm[selector]); break;
-                                       case 16:        if (dec) f->waveform--; else f->waveform++;
-                                                       adlib_update_groupE0(operator,f); break;
-                               };
-
-                               redrawln=1;
-                       }
-                       else if (c == 0x4800) {
-                               if (selectsub && !(hselect >= 11 && hselect <= 15)) {
-                                       selectsub = 0;
-                                       redrawln = 1;
-                               }
-                               else if (selector > 0) {
-                                       selectsub = !(hselect >= 11 && hselect <= 15);
-                                       selector--;
-                                       redrawln = 1;
-                               }
-                       }
-                       else if (c == 0x4B00) {
-                               if (hselect > 0) {
-                                       hselect--;
-                                       redrawln=1;
-                               }
-                       }
-                       else if (c == 0x4D00) {
-                               if (hselect < 17) {
-                                       hselect++;
-                                       redrawln=1;
-                               }
-                       }
-                       else if (c == 0x5000) {
-                               if (selectsub == 0 && !(hselect >= 11 && hselect <= 15)) {
-                                       selectsub = 1;
-                                       redrawln = 1;
-                               }
-                               else if ((selector+1) < adlib_fm_voices) {
-                                       selectsub = 0;
-                                       selector++;
-                                       redrawln=1;
-                               }
-                       }
-
-               }
-       }
-
-       shutdown_adlib();
-       int10_setmode(3);
-
-       return 0;
-}
-
+/* test.c\r
+ *\r
+ * Adlib OPL2/OPL3 FM synthesizer chipset test program.\r
+ * (C) 2010-2012 Jonathan Campbell.\r
+ * Hackipedia DOS library.\r
+ *\r
+ * This code is licensed under the LGPL.\r
+ * <insert LGPL legal text here>\r
+ *\r
+ * Compiles for intended target environments:\r
+ *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]\r
+ *\r
+ * This test program uses a "text user interface" to allow you to play\r
+ * with the OPL2/OPL3 chipset and it's parameters. Some "instruments"\r
+ * are preset for you if you want to make noise faster.\r
+ */\r
\r
+#include <stdio.h>\r
+#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <malloc.h>\r
+#include <ctype.h>\r
+#include <fcntl.h>\r
+#include <dos.h>\r
+\r
+#include <hw/vga/vga.h>\r
+#include <hw/dos/dos.h>\r
+#include <hw/8254/8254.h>              /* 8254 timer */\r
+#include <hw/vga/vgagui.h>\r
+#include <hw/vga/vgatty.h>\r
+#include <hw/adlib/adlib.h>\r
+\r
+static unsigned int musical_scale[18] = {\r
+       0x1B0,                  /* E */\r
+       0x1CA,                  /* F */\r
+       0x1E5,                  /* f# */\r
+       0x202,                  /* G */\r
+       0x220,                  /* G# */\r
+       0x241,                  /* A */\r
+       0x263,                  /* A# */\r
+       0x287,                  /* B */\r
+       0x2AE,                  /* C */\r
+\r
+       0x2B0,                  /* E */\r
+       0x2CA,                  /* F */\r
+       0x2E5,                  /* f# */\r
+       0x302,                  /* G */\r
+       0x320,                  /* G# */\r
+       0x341,                  /* A */\r
+       0x363,                  /* A# */\r
+       0x387,                  /* B */\r
+       0x3AE,                  /* C */\r
+};\r
+\r
+int main(int argc,char **argv) {\r
+       int i,loop,redraw,c,cc,selector=0,redrawln=0,hselect=0,selectsub=0;\r
+       VGA_ALPHA_PTR vga;\r
+       char tmp[128];\r
+\r
+       printf("ADLIB FM test program\n");\r
+\r
+       if (!probe_vga()) {\r
+               printf("Cannot init VGA\n");\r
+               return 1;\r
+       }\r
+       if (!init_adlib()) {\r
+               printf("Cannot init library\n");\r
+               return 1;\r
+       }\r
+\r
+       int10_setmode(3);\r
+\r
+       /* for VGA: free up space if needed by going to 80x50 */\r
+       if (adlib_fm_voices > 9)\r
+               vga_bios_set_80x50_text();\r
+\r
+       memset(adlib_fm,0,sizeof(adlib_fm));\r
+       memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));\r
+       for (i=0;i < adlib_fm_voices;i++) {\r
+               struct adlib_fm_operator *f;\r
+               f = &adlib_fm[i].mod;\r
+               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\r
+               f = &adlib_fm[i].car;\r
+               f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\r
+       }\r
+\r
+       for (i=0;i < adlib_fm_voices;i++) {\r
+               struct adlib_fm_operator *f;\r
+\r
+               f = &adlib_fm[i].mod;\r
+               f->mod_multiple = 1;\r
+               f->total_level = 63 - 16;\r
+               f->attack_rate = 15;\r
+               f->decay_rate = 0;\r
+               f->sustain_level = 7;\r
+               f->release_rate = 7;\r
+               f->f_number = musical_scale[i%18];\r
+               f->octave = 4;\r
+               f->key_on = 0;\r
+\r
+               f = &adlib_fm[i].car;\r
+               f->mod_multiple = 1;\r
+               f->total_level = 63 - 16;\r
+               f->attack_rate = 15;\r
+               f->decay_rate = 0;\r
+               f->sustain_level = 7;\r
+               f->release_rate = 7;\r
+               f->f_number = 0;\r
+               f->octave = 0;\r
+               f->key_on = 0;\r
+       }\r
+\r
+       adlib_apply_all();\r
+\r
+       vga_write_color(0x07);\r
+       vga_clear();\r
+\r
+       loop=1;\r
+       redraw=1;\r
+       while (loop) {\r
+               if (redraw || redrawln) {\r
+                       if (redraw) {\r
+                               for (vga=vga_alpha_ram,cc=0;cc < (80*vga_height);cc++) *vga++ = 0x1E00 | 177;\r
+                               vga_moveto(0,0);\r
+                               vga_write_color(0x1F);\r
+                               sprintf(tmp,"Adlib FM, %u-voice %s. Use Z & X to adj  F10=PRESET F1=QUIET ",adlib_fm_voices,\r
+                                       (adlib_flags & ADLIB_FM_OPL3) ? "OPL3" :\r
+                                       (adlib_flags & ADLIB_FM_DUAL_OPL2) ? "Dual OPL2" : "OPL2");\r
+                               vga_write(tmp);\r
+                               if (adlib_flags & ADLIB_FM_OPL3) vga_write("F2=OPL3 off ");\r
+                       }\r
+\r
+                       if (redrawln || redraw) {\r
+                               struct adlib_reg_bd *bd = &adlib_reg_bd;\r
+                               static const char *hsel_str[18] = {\r
+                                       "Amplitude modulatation",\r
+                                       "Vibrato",\r
+                                       "Sustain",\r
+                                       "Key scaling rate",\r
+                                       "Modulator frequency multiple",\r
+                                       "Level key scaling",\r
+                                       "Total level",\r
+                                       "Attack rate",\r
+                                       "Decay rate",\r
+                                       "Sustain level",\r
+                                       "Release rate",\r
+                                       "KEY ON",\r
+                                       "Octave",\r
+                                       "F-Number",\r
+                                       "Feedback",\r
+                                       "Connection (operator 1 -> operator 2)",\r
+                                       "Waveform",\r
+                                       "Channel mapping (OPL3)"\r
+                               };\r
+\r
+                               vga_write_color(0x1A);\r
+\r
+                               vga_moveto(0,2);\r
+                               sprintf(tmp,"AM=%u VB=%u RYTHM=%u BAS=%u SNA=%u TOM=%u CYM=%u HI=%u\n",\r
+                                       bd->am_depth,\r
+                                       bd->vibrato_depth,\r
+                                       bd->rythm_enable,\r
+                                       bd->bass_drum_on,\r
+                                       bd->snare_drum_on,\r
+                                       bd->tom_tom_on,\r
+                                       bd->cymbal_on,\r
+                                       bd->hi_hat_on);\r
+                               vga_write(tmp);\r
+\r
+                               vga_moveto(0,3);\r
+                               vga_write("                                                       ");\r
+                               vga_moveto(0,3);\r
+                               vga_write(hsel_str[hselect]);\r
+\r
+                               vga_moveto(0,4);\r
+                               vga_write_color(hselect ==  0 ? 0x70 : 0x1E);           vga_write("AM ");\r
+                               vga_write_color(hselect ==  1 ? 0x70 : 0x1E);           vga_write("VB ");\r
+                               vga_write_color(hselect ==  2 ? 0x70 : 0x1E);           vga_write("SUST ");\r
+                               vga_write_color(hselect ==  3 ? 0x70 : 0x1E);           vga_write("KSR ");\r
+                               vga_write_color(hselect ==  4 ? 0x70 : 0x1E);           vga_write("MMUL ");\r
+                               vga_write_color(hselect ==  5 ? 0x70 : 0x1E);           vga_write("LKS ");\r
+                               vga_write_color(hselect ==  6 ? 0x70 : 0x1E);           vga_write("TL ");\r
+                               vga_write_color(hselect ==  7 ? 0x70 : 0x1E);           vga_write("AR ");\r
+                               vga_write_color(hselect ==  8 ? 0x70 : 0x1E);           vga_write("DR ");\r
+                               vga_write_color(hselect ==  9 ? 0x70 : 0x1E);           vga_write("SL ");\r
+                               vga_write_color(hselect == 10 ? 0x70 : 0x1E);           vga_write("RR ");\r
+                               vga_write_color(hselect == 11 ? 0x70 : 0x1E);           vga_write("KEY ");\r
+                               vga_write_color(hselect == 12 ? 0x70 : 0x1E);           vga_write("OCT ");\r
+                               vga_write_color(hselect == 13 ? 0x70 : 0x1E);           vga_write("FNUM ");\r
+                               vga_write_color(hselect == 14 ? 0x70 : 0x1E);           vga_write("FEED ");\r
+                               vga_write_color(hselect == 15 ? 0x70 : 0x1E);           vga_write("CON ");\r
+                               vga_write_color(hselect == 16 ? 0x70 : 0x1E);           vga_write("WV ");\r
+                               vga_write_color(hselect == 17 ? 0x70 : 0x1E);           vga_write("ABCD ");\r
+\r
+                               for (i=0;i < adlib_fm_voices;i++) {\r
+                                       struct adlib_fm_operator *f;\r
+                                       double freq;\r
+                                       \r
+                                       f = &adlib_fm[i].mod;\r
+                                       vga_moveto(0,5+i*2);\r
+                                       freq = adlib_fm_op_to_freq(f);\r
+                                       vga_write_color(i == selector && selectsub == 0 ? 0x70 : 0x1E);\r
+                                       cc = sprintf(tmp,"%u  %u  %u    %u   %-2u   %u   %-2u %-2u %-2u %-2u %-2u %u   %u   %-4u %u    %u   %u  %c%c%c%c %u %.1fHz ",\r
+                                               f->am,                  f->vibrato,             f->sustain,             f->key_scaling_rate,\r
+                                               f->mod_multiple,        f->level_key_scale,     f->total_level,         f->attack_rate,\r
+                                               f->decay_rate,          f->sustain_level,       f->release_rate,        f->key_on,\r
+                                               f->octave,              f->f_number,            f->feedback,            f->connection,\r
+                                               f->waveform,            f->ch_a?'*':'-',        f->ch_b?'*':'-',        f->ch_c?'*':'-',\r
+                                               f->ch_d?'*':'-',        i+1,                    freq);\r
+                                       vga_write(tmp);\r
+\r
+                                       f = &adlib_fm[i].car;\r
+                                       vga_moveto(0,5+i*2+1);\r
+                                       vga_write_color(i == selector && selectsub == 1 ? 0x70 : 0x1E);\r
+                                       cc = sprintf(tmp,"%u  %u  %u    %u   %-2u   %u   %-2u %-2u %-2u %-2u %-2u                       %u       CAR   ",\r
+                                               f->am,                  f->vibrato,             f->sustain,             f->key_scaling_rate,\r
+                                               f->mod_multiple,        f->level_key_scale,     f->total_level,         f->attack_rate,\r
+                                               f->decay_rate,          f->sustain_level,       f->release_rate,        f->waveform);\r
+                                       vga_write(tmp);\r
+                               }\r
+                       }\r
+\r
+                       redrawln = 0;\r
+                       redraw = 0;\r
+               }\r
+\r
+               if (kbhit()) {\r
+                       c = getch();\r
+                       if (c == 0) c = getch() << 8;\r
+\r
+                       if (c == 27) {\r
+                               loop = 0;\r
+                       }\r
+                       else if (c == 0x3B00) { /* F1 */\r
+                               for (i=0;i < adlib_fm_voices;i++) {\r
+                                       adlib_fm[i].mod.key_on = 0;\r
+                                       adlib_fm[i].car.key_on = 0;\r
+                                       adlib_update_groupA0(i,&adlib_fm[i]);\r
+                               }\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 0x3C00) { /* F2 */\r
+                               if (adlib_flags & ADLIB_FM_OPL3) {\r
+                                       shutdown_adlib_opl3();\r
+                                       int10_setmode(3);\r
+                                       redraw = 1;\r
+                               }\r
+                       }\r
+                       else if (c == 0x4400) { /* F10 */\r
+                               unsigned short op = adlib_voice_to_op[selector];\r
+\r
+                               vga_write_color(0x07);\r
+                               vga_clear();\r
+                               vga_moveto(0,0);\r
+\r
+                               vga_write("Choose an instrument to load into the channel:\n");\r
+                               vga_write(" 1. Violin     2. Piano     3. Harpsichord     4. Horn      5. Deep bass drum\n");\r
+                               vga_write(" 6. Small drum \n");\r
+                               vga_write_sync();\r
+\r
+                               c = getch();\r
+\r
+                               if (c == '1')\r
+                                       adlib_fm[selector] =\r
+                                               (adlib_flags & ADLIB_FM_OPL3 ?\r
+                                                adlib_fm_preset_violin_opl3 : adlib_fm_preset_violin_opl2);\r
+                               else if (c == '2')\r
+                                       adlib_fm[selector] = adlib_fm_preset_piano;\r
+                               else if (c == '3')\r
+                                       adlib_fm[selector] = adlib_fm_preset_harpsichord;\r
+                               else if (c == '4')\r
+                                       adlib_fm[selector] = adlib_fm_preset_horn;\r
+                               else if (c == '5')\r
+                                       adlib_fm[selector] = adlib_fm_preset_deep_bass_drum;\r
+                               else if (c == '6')\r
+                                       adlib_fm[selector] = adlib_fm_preset_small_drum;\r
+\r
+                               adlib_update_groupA0(selector,&adlib_fm[selector]);\r
+                               adlib_update_groupC0(selector,&adlib_fm[selector]);\r
+                               adlib_update_operator(op,&adlib_fm[selector].mod);\r
+                               adlib_update_operator(op+3,&adlib_fm[selector].car);\r
+\r
+                               redraw = 1;\r
+                       }\r
+                       else if (c == ' ') {\r
+                               adlib_fm[selector].mod.key_on ^= 1;\r
+                               adlib_update_groupA0(selector,&adlib_fm[selector]);\r
+                               redrawln=1;\r
+                       }\r
+                       else if (c == 'a') {\r
+                               if (hselect == 17) {\r
+                                       struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_a ^= 1;\r
+                                       adlib_update_groupC0(selector,&adlib_fm[selector]);\r
+                               }\r
+                               else {\r
+                                       adlib_reg_bd.am_depth ^= 1;\r
+                                       adlib_update_bd(&adlib_reg_bd);\r
+                               }\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 'v') {\r
+                               adlib_reg_bd.vibrato_depth ^= 1;\r
+                               adlib_update_bd(&adlib_reg_bd);\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 'r') {\r
+                               adlib_reg_bd.rythm_enable ^= 1;\r
+                               adlib_update_bd(&adlib_reg_bd);\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 'b') {\r
+                               if (hselect == 17) {\r
+                                       struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_b ^= 1;\r
+                                       adlib_update_groupC0(selector,&adlib_fm[selector]);\r
+                               }\r
+                               else {\r
+                                       adlib_reg_bd.bass_drum_on ^= 1;\r
+                                       adlib_update_bd(&adlib_reg_bd);\r
+                               }\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 's') {\r
+                               adlib_reg_bd.snare_drum_on ^= 1;\r
+                               adlib_update_bd(&adlib_reg_bd);\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 't') {\r
+                               adlib_reg_bd.tom_tom_on ^= 1;\r
+                               adlib_update_bd(&adlib_reg_bd);\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 'c') {\r
+                               if (hselect == 17) {\r
+                                       struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_c ^= 1;\r
+                                       adlib_update_groupC0(selector,&adlib_fm[selector]);\r
+                               }\r
+                               else {\r
+                                       adlib_reg_bd.cymbal_on ^= 1;\r
+                                       adlib_update_bd(&adlib_reg_bd);\r
+                               }\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 'd') {\r
+                               if (hselect == 17) {\r
+                                       struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_d ^= 1;\r
+                                       adlib_update_groupC0(selector,&adlib_fm[selector]);\r
+                               }\r
+                               else {\r
+                               }\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 'h') {\r
+                               adlib_reg_bd.hi_hat_on ^= 1;\r
+                               adlib_update_bd(&adlib_reg_bd);\r
+                               redrawln = 1;\r
+                       }\r
+                       else if (c == 'z' || c == 'Z' || c == 'x' || c == 'X') {\r
+                               struct adlib_fm_operator *f;\r
+                               int dec = tolower(c) == 'z';\r
+                               unsigned short operator;\r
+\r
+                               switch (hselect) {\r
+                                       case 11:selectsub = 0;\r
+                                               break;\r
+                               }\r
+\r
+                               if (selectsub) f = &adlib_fm[selector].car;\r
+                               else           f = &adlib_fm[selector].mod;\r
+                               operator = adlib_voice_to_op[selector] + (selectsub*3);\r
+\r
+                               switch (hselect) {\r
+                                       case 0:         f->am ^= 1;                     adlib_update_group20(operator,f); break;\r
+                                       case 11:        f->key_on ^= 1;                 adlib_update_groupA0(selector,&adlib_fm[selector]); break;\r
+                                       case 1:         f->vibrato ^= 1;                adlib_update_group20(operator,f); break;\r
+                                       case 2:         f->sustain ^= 1;                adlib_update_group20(operator,f); break;\r
+                                       case 15:        f->connection ^= 1;             adlib_update_group20(operator,f); break;\r
+                                       case 3:         f->key_scaling_rate ^= 1;       adlib_update_group20(operator,f); break;\r
+\r
+                                       case 4:         if (dec) f->mod_multiple--; else f->mod_multiple++;\r
+                                                       adlib_update_group20(operator,f); break;\r
+                                       case 5:         if (dec) f->level_key_scale--; else f->level_key_scale++;\r
+                                                       adlib_update_group40(operator,f); break;\r
+                                       case 6:         if (dec) f->total_level--; else f->total_level++;\r
+                                                       adlib_update_group40(operator,f); break;\r
+                                       case 7:         if (dec) f->attack_rate--; else f->attack_rate++;\r
+                                                       adlib_update_group60(operator,f); break;\r
+                                       case 8:         if (dec) f->decay_rate--; else f->decay_rate++;\r
+                                                       adlib_update_group60(operator,f); break;\r
+                                       case 9:         if (dec) f->sustain_level--; else f->sustain_level++;\r
+                                                       adlib_update_group80(operator,f); break;\r
+                                       case 10:        if (dec) f->release_rate--; else f->release_rate++;\r
+                                                       adlib_update_group80(operator,f); break;\r
+                                       case 12:        if (dec) f->octave--; else f->octave++;\r
+                                                       adlib_update_groupA0(selector,&adlib_fm[selector]); break;\r
+                                       case 13:        if (dec) f->f_number--; else f->f_number++;\r
+                                                       adlib_update_groupA0(selector,&adlib_fm[selector]); break;\r
+                                       case 14:        if (dec) f->feedback--; else f->feedback++;\r
+                                                       adlib_update_groupC0(selector,&adlib_fm[selector]); break;\r
+                                       case 16:        if (dec) f->waveform--; else f->waveform++;\r
+                                                       adlib_update_groupE0(operator,f); break;\r
+                               };\r
+\r
+                               redrawln=1;\r
+                       }\r
+                       else if (c == 0x4800) {\r
+                               if (selectsub && !(hselect >= 11 && hselect <= 15)) {\r
+                                       selectsub = 0;\r
+                                       redrawln = 1;\r
+                               }\r
+                               else if (selector > 0) {\r
+                                       selectsub = !(hselect >= 11 && hselect <= 15);\r
+                                       selector--;\r
+                                       redrawln = 1;\r
+                               }\r
+                       }\r
+                       else if (c == 0x4B00) {\r
+                               if (hselect > 0) {\r
+                                       hselect--;\r
+                                       redrawln=1;\r
+                               }\r
+                       }\r
+                       else if (c == 0x4D00) {\r
+                               if (hselect < 17) {\r
+                                       hselect++;\r
+                                       redrawln=1;\r
+                               }\r
+                       }\r
+                       else if (c == 0x5000) {\r
+                               if (selectsub == 0 && !(hselect >= 11 && hselect <= 15)) {\r
+                                       selectsub = 1;\r
+                                       redrawln = 1;\r
+                               }\r
+                               else if ((selector+1) < adlib_fm_voices) {\r
+                                       selectsub = 0;\r
+                                       selector++;\r
+                                       redrawln=1;\r
+                               }\r
+                       }\r
+\r
+               }\r
+       }\r
+\r
+       shutdown_adlib();\r
+       int10_setmode(3);\r
+\r
+       return 0;\r
+}\r
+\r
index 83f3712eef3d0bfea0dd774f8bef9b0eac2b67f5..ab7e2db64924be9a4ca49e3aa1edcedfedf1267e 100755 (executable)
-#include <hw/cpu/cpu.h>
-#include <hw/dos/dos.h>
-#include <hw/vga/vga.h>
-#include <hw/vga/vrl.h>
-
-#include "src/tesuto.h"
-
-static unsigned char palette[768];
-
-int main(int argc,char **argv) {
-       struct vrl1_vgax_header *vrl_header;
-       vrl1_vgax_offset_t *vrl_lineoffs;
-       unsigned char *buffer;
-       unsigned int bufsz;
-       int fd;
-
-       if (argc < 3) {
-               fprintf(stderr,"drawvrl <VRL file> <palette file>\n");
-               return 1;
-       }
-
-       fd = open(argv[1],O_RDONLY|O_BINARY);
-       if (fd < 0) {
-               fprintf(stderr,"Unable to open '%s'\n",argv[1]);
-               return 1;
-       }
-       {
-               unsigned long sz = lseek(fd,0,SEEK_END);
-               if (sz < sizeof(*vrl_header)) return 1;
-               if (sz >= 65535UL) return 1;
-
-               bufsz = (unsigned int)sz;
-               buffer = malloc(bufsz);
-               if (buffer == NULL) return 1;
-
-               lseek(fd,0,SEEK_SET);
-               if ((unsigned int)read(fd,buffer,bufsz) < bufsz) return 1;
-
-               vrl_header = (struct vrl1_vgax_header*)buffer;
-               if (memcmp(vrl_header->vrl_sig,"VRL1",4) || memcmp(vrl_header->fmt_sig,"VGAX",4)) return 1;
-               if (vrl_header->width == 0 || vrl_header->height == 0) return 1;
-       }
-       close(fd);
-
-       probe_dos();
-       if (!probe_vga()) {
-               printf("VGA probe failed\n");
-               return 1;
-       }
-       int10_setmode(19);
-       update_state_from_vga();
-       vga_enable_256color_modex(); // VGA mode X
-       vga_state.vga_width = 320; // VGA lib currently does not update this
-       vga_state.vga_height = 240; // VGA lib currently does not update this
-
-#if 1 // 320x240 test mode: this is how Project 16 is using our code, enable for test case
-       {
-               struct vga_mode_params cm;
-
-               vga_read_crtc_mode(&cm);
-
-               // 320x240 mode 60Hz
-               cm.vertical_total = 525;
-               cm.vertical_start_retrace = 0x1EA;
-               cm.vertical_end_retrace = 0x1EC;
-               cm.vertical_display_end = 480;
-               cm.vertical_blank_start = 489;
-               cm.vertical_blank_end = 517;
-
-               vga_write_crtc_mode(&cm,0);
-       }
-       vga_state.vga_height = 240; // VGA lib currently does not update this
-#endif
-
-       /* load color palette */
-       fd = open(argv[2],O_RDONLY|O_BINARY);
-       if (fd >= 0) {
-               unsigned int i;
-
-               read(fd,palette,768);
-               close(fd);
-
-               vga_palette_lseek(0);
-               for (i=0;i < 256;i++) vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);
-       }
-
-       /* preprocess the sprite to generate line offsets */
-       vrl_lineoffs = vrl1_vgax_genlineoffsets(vrl_header,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));
-       if (vrl_lineoffs == NULL) return 1;
-
-       {
-               unsigned int i,j,o;
-
-               /* fill screen with a distinctive pattern */
-               for (i=0;i < vga_state.vga_width;i++) {
-                       o = i >> 2;
-                       vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
-                       for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride)
-                               vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
-               }
-       }
-       //while (getch() != 13);
-
-       /* make distinctive pattern offscreen, render sprite, copy onscreen */
-       {
-               const unsigned int offscreen_ofs = (vga_state.vga_stride * vga_state.vga_height);
-               unsigned int i,j,o,o2,x,y,rx,ry,w,h;
-               unsigned int overdraw = 1;      // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks.
-                                               // if the sprite's edge pixels are clear anyway, you can set this to 0.
-               VGA_RAM_PTR omemptr;
-               int xdir=1,ydir=1;
-
-               /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */
-               x = 0;
-               y = 0;
-
-               /* do it */
-               omemptr = vga_state.vga_graphics_ram; // save original mem ptr
-               while (1) {
-                       /* stop animating if the user hits ENTER */
-                       if (kbhit()) {
-                               if (getch() == 13) break;
-                       }
-
-                       /* render box bounds. y does not need modification, but x and width must be multiple of 4 */
-                       if (x >= overdraw) rx = (x - overdraw) & (~3);
-                       else rx = 0;
-                       if (y >= overdraw) ry = (y - overdraw);
-                       else ry = 0;
-                       h = vrl_header->height + overdraw + y - ry;
-                       w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3);
-                       if ((rx+w) > vga_state.vga_width) w = vga_state.vga_width-rx;
-                       if ((ry+h) > vga_state.vga_height) h = vga_state.vga_height-ry;
-
-                       /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */
-                       vga_state.vga_draw_stride_limit = (vga_state.vga_width + 3/*round up*/ - x) >> 2;
-                       vga_state.vga_draw_stride = w >> 2;
-                       vga_state.vga_graphics_ram = omemptr + offscreen_ofs;
-
-                       /* first draw pattern corresponding to that part of the screen. this COULD be optimized, obviously, but it's designed for study.
-                        * also note we don't have to use the same stride as the display! */
-                       for (i=rx;i < (rx+w);i++) {
-                               o = (i-rx) >> 2;
-                               vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
-                               for (j=ry;j < (ry+h);j++,o += vga_state.vga_draw_stride)
-                                       vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
-                       }
-
-                       /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */
-                       draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));
-
-                       /* restore ptr */
-                       vga_state.vga_graphics_ram = omemptr;
-
-                       /* block copy to visible RAM from offscreen */
-                       vga_setup_wm1_block_copy();
-                       o = offscreen_ofs; // source offscreen
-                       o2 = (ry * vga_state.vga_stride) + (rx >> 2); // dest visible (original stride)
-                       for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);
-                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */
-                       vga_restore_rm0wm0();
-
-                       /* restore stride */
-                       vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride;
-
-                       /* step */
-                       x += xdir;
-                       y += ydir;
-                       if (x >= (vga_state.vga_width - 1) || x == 0)
-                               xdir = -xdir;
-                       if (y >= (vga_state.vga_height - 1) || y == 0)
-                               ydir = -ydir;
-               }
-       }
-
-       /* make distinctive pattern offscreen, render sprite, copy onscreen.
-        * this time, we render the distinctive pattern to another offscreen location and just copy.
-        * note this version is much faster too! */
-       {
-               const unsigned int offscreen_ofs = (vga_state.vga_stride * vga_state.vga_height);
-               const unsigned int pattern_ofs = 0x10000UL - (vga_state.vga_stride * vga_state.vga_height);
-               unsigned int i,j,o,o2,x,y,rx,ry,w,h;
-               unsigned int overdraw = 1;      // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks.
-                                               // if the sprite's edge pixels are clear anyway, you can set this to 0.
-               VGA_RAM_PTR omemptr;
-               int xdir=1,ydir=1;
-
-               /* fill pattern offset with a distinctive pattern */
-               for (i=0;i < vga_state.vga_width;i++) {
-                       o = (i >> 2) + pattern_ofs;
-                       vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
-                       for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride)
-                               vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
-               }
-
-               /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */
-               x = 0;
-               y = 0;
-
-               /* do it */
-               omemptr = vga_state.vga_graphics_ram; // save original mem ptr
-               while (1) {
-                       /* stop animating if the user hits ENTER */
-                       if (kbhit()) {
-                               if (getch() == 13) break;
-                       }
-
-                       /* render box bounds. y does not need modification, but x and width must be multiple of 4 */
-                       if (x >= overdraw) rx = (x - overdraw) & (~3);
-                       else rx = 0;
-                       if (y >= overdraw) ry = (y - overdraw);
-                       else ry = 0;
-                       h = vrl_header->height + overdraw + y - ry;
-                       w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3);
-                       if ((rx+w) > vga_state.vga_width) w = vga_state.vga_width-rx;
-                       if ((ry+h) > vga_state.vga_height) h = vga_state.vga_height-ry;
-
-                       /* block copy pattern to where we will draw the sprite */
-                       vga_setup_wm1_block_copy();
-                       o2 = offscreen_ofs;
-                       o = pattern_ofs + (ry * vga_state.vga_stride) + (rx >> 2); // source offscreen
-                       for (i=0;i < h;i++,o += vga_state.vga_stride,o2 += (w >> 2)) vga_wm1_mem_block_copy(o2,o,w >> 2);
-                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */
-                       vga_restore_rm0wm0();
-
-                       /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */
-                       vga_state.vga_draw_stride_limit = (vga_state.vga_width + 3/*round up*/ - x) >> 2;
-                       vga_state.vga_draw_stride = w >> 2;
-                       vga_state.vga_graphics_ram = omemptr + offscreen_ofs;
-
-                       /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */
-                       draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));
-
-                       /* restore ptr */
-                       vga_state.vga_graphics_ram = omemptr;
-
-                       /* block copy to visible RAM from offscreen */
-                       vga_setup_wm1_block_copy();
-                       o = offscreen_ofs; // source offscreen
-                       o2 = (ry * vga_state.vga_stride) + (rx >> 2); // dest visible (original stride)
-                       for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);
-                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */
-                       vga_restore_rm0wm0();
-
-                       /* restore stride */
-                       vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride;
-
-                       /* step */
-                       x += xdir;
-                       y += ydir;
-                       if (x >= (vga_state.vga_width - 1) || x == 0)
-                               xdir = -xdir;
-                       if (y >= (vga_state.vga_height - 1) || y == 0)
-                               ydir = -ydir;
-               }
-       }
-
-       /* another handy "demo" effect using VGA write mode 1.
-        * we can take what's on screen and vertically squash it like an old analog TV set turning off. */
-       {
-               unsigned int blank_line_ofs = (vga_state.vga_stride * vga_state.vga_height * 2);
-               unsigned int copy_ofs = (vga_state.vga_stride * vga_state.vga_height);
-               unsigned int display_ofs = 0x0000;
-               unsigned int i,y,soh,doh,dstart;
-               unsigned int dh_blankfill = 8;
-               unsigned int dh_step = 8;
-               uint32_t sh,dh,yf,ystep;
-
-               /* copy active display (0) to offscreen buffer (0x4000) */
-               vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride;
-               vga_setup_wm1_block_copy();
-               vga_wm1_mem_block_copy(copy_ofs,display_ofs,vga_state.vga_stride * vga_state.vga_height);
-               vga_restore_rm0wm0();
-
-               /* need a blank line as well */
-               for (i=0;i < vga_state.vga_stride;i++) vga_state.vga_graphics_ram[i+blank_line_ofs] = 0;
-
-               sh = dh = vga_state.vga_height;
-               while (dh >= dh_step) {
-                       /* stop animating if the user hits ENTER */
-                       if (kbhit()) {
-                               if (getch() == 13) break;
-                       }
-
-                       /* wait for vsync end */
-                       vga_wait_for_vsync_end();
-
-                       /* what scalefactor to use for stretching? */
-                       ystep = (0x10000UL * sh) / dh;
-                       dstart = (vga_state.vga_height - dh) / 2; // center the squash effect on screen, otherwise it would squash to top of screen
-                       doh = display_ofs;
-                       soh = copy_ofs;
-                       yf = 0;
-                       y = 0;
-
-                       /* for performance, keep VGA in write mode 1 the entire render */
-                       vga_setup_wm1_block_copy();
-
-                       /* blank lines */
-                       if (dstart >= dh_blankfill) y = dstart - dh_blankfill;
-                       else y = 0;
-                       doh = vga_state.vga_stride * y;
-
-                       while (y < dstart) {
-                               vga_wm1_mem_block_copy(doh,blank_line_ofs,vga_state.vga_stride);
-                               doh += vga_state.vga_stride;
-                               y++;
-                       }
-
-                       /* draw */
-                       while (y < (dh+dstart)) {
-                               soh = copy_ofs + ((yf >> 16UL) * vga_state.vga_stride);
-                               vga_wm1_mem_block_copy(doh,soh,vga_state.vga_stride);
-                               doh += vga_state.vga_stride;
-                               yf += ystep;
-                               y++;
-                       }
-
-                       /* blank lines */
-                       while (y < vga_state.vga_height && y < (dh+dstart+dh_blankfill)) {
-                               vga_wm1_mem_block_copy(doh,blank_line_ofs,vga_state.vga_stride);
-                               doh += vga_state.vga_stride;
-                               y++;
-                       }
-
-                       /* done */
-                       vga_restore_rm0wm0();
-
-                       /* wait for vsync */
-                       vga_wait_for_vsync();
-
-                       /* make it shrink */
-                       dh -= dh_step;
-                       if (dh < 40) dh_step = 1;
-               }
-       }
-
-       int10_setmode(3);
-       free(vrl_lineoffs);
-       buffer = NULL;
-       free(buffer);
-       bufsz = 0;
-       return 0;
-}
+#include <hw/cpu/cpu.h>\r
+#include <hw/dos/dos.h>\r
+#include <hw/vga/vga.h>\r
+#include <hw/vga/vrl.h>\r
+\r
+#include "src/tesuto.h"\r
+\r
+static unsigned char palette[768];\r
+\r
+int main(int argc,char **argv) {\r
+       struct vrl1_vgax_header *vrl_header;\r
+       vrl1_vgax_offset_t *vrl_lineoffs;\r
+       unsigned char *buffer;\r
+       unsigned int bufsz;\r
+       int fd;\r
+\r
+       if (argc < 3) {\r
+               fprintf(stderr,"drawvrl <VRL file> <palette file>\n");\r
+               return 1;\r
+       }\r
+\r
+       fd = open(argv[1],O_RDONLY|O_BINARY);\r
+       if (fd < 0) {\r
+               fprintf(stderr,"Unable to open '%s'\n",argv[1]);\r
+               return 1;\r
+       }\r
+       {\r
+               unsigned long sz = lseek(fd,0,SEEK_END);\r
+               if (sz < sizeof(*vrl_header)) return 1;\r
+               if (sz >= 65535UL) return 1;\r
+\r
+               bufsz = (unsigned int)sz;\r
+               buffer = malloc(bufsz);\r
+               if (buffer == NULL) return 1;\r
+\r
+               lseek(fd,0,SEEK_SET);\r
+               if ((unsigned int)read(fd,buffer,bufsz) < bufsz) return 1;\r
+\r
+               vrl_header = (struct vrl1_vgax_header*)buffer;\r
+               if (memcmp(vrl_header->vrl_sig,"VRL1",4) || memcmp(vrl_header->fmt_sig,"VGAX",4)) return 1;\r
+               if (vrl_header->width == 0 || vrl_header->height == 0) return 1;\r
+       }\r
+       close(fd);\r
+\r
+       probe_dos();\r
+       if (!probe_vga()) {\r
+               printf("VGA probe failed\n");\r
+               return 1;\r
+       }\r
+       int10_setmode(19);\r
+       update_state_from_vga();\r
+       vga_enable_256color_modex(); // VGA mode X\r
+       vga_state.vga_width = 320; // VGA lib currently does not update this\r
+       vga_state.vga_height = 240; // VGA lib currently does not update this\r
+\r
+#if 1 // 320x240 test mode: this is how Project 16 is using our code, enable for test case\r
+       {\r
+               struct vga_mode_params cm;\r
+\r
+               vga_read_crtc_mode(&cm);\r
+\r
+               // 320x240 mode 60Hz\r
+               cm.vertical_total = 525;\r
+               cm.vertical_start_retrace = 0x1EA;\r
+               cm.vertical_end_retrace = 0x1EC;\r
+               cm.vertical_display_end = 480;\r
+               cm.vertical_blank_start = 489;\r
+               cm.vertical_blank_end = 517;\r
+\r
+               vga_write_crtc_mode(&cm,0);\r
+       }\r
+       vga_state.vga_height = 240; // VGA lib currently does not update this\r
+#endif\r
+\r
+       /* load color palette */\r
+       fd = open(argv[2],O_RDONLY|O_BINARY);\r
+       if (fd >= 0) {\r
+               unsigned int i;\r
+\r
+               read(fd,palette,768);\r
+               close(fd);\r
+\r
+               vga_palette_lseek(0);\r
+               for (i=0;i < 256;i++) vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);\r
+       }\r
+\r
+       /* preprocess the sprite to generate line offsets */\r
+       vrl_lineoffs = vrl1_vgax_genlineoffsets(vrl_header,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));\r
+       if (vrl_lineoffs == NULL) return 1;\r
+\r
+       {\r
+               unsigned int i,j,o;\r
+\r
+               /* fill screen with a distinctive pattern */\r
+               for (i=0;i < vga_state.vga_width;i++) {\r
+                       o = i >> 2;\r
+                       vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
+                       for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride)\r
+                               vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
+               }\r
+       }\r
+       //while (getch() != 13);\r
+\r
+       /* make distinctive pattern offscreen, render sprite, copy onscreen */\r
+       {\r
+               const unsigned int offscreen_ofs = (vga_state.vga_stride * vga_state.vga_height);\r
+               unsigned int i,j,o,o2,x,y,rx,ry,w,h;\r
+               unsigned int overdraw = 1;      // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks.\r
+                                               // if the sprite's edge pixels are clear anyway, you can set this to 0.\r
+               VGA_RAM_PTR omemptr;\r
+               int xdir=1,ydir=1;\r
+\r
+               /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */\r
+               x = 0;\r
+               y = 0;\r
+\r
+               /* do it */\r
+               omemptr = vga_state.vga_graphics_ram; // save original mem ptr\r
+               while (1) {\r
+                       /* stop animating if the user hits ENTER */\r
+                       if (kbhit()) {\r
+                               if (getch() == 13) break;\r
+                       }\r
+\r
+                       /* render box bounds. y does not need modification, but x and width must be multiple of 4 */\r
+                       if (x >= overdraw) rx = (x - overdraw) & (~3);\r
+                       else rx = 0;\r
+                       if (y >= overdraw) ry = (y - overdraw);\r
+                       else ry = 0;\r
+                       h = vrl_header->height + overdraw + y - ry;\r
+                       w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3);\r
+                       if ((rx+w) > vga_state.vga_width) w = vga_state.vga_width-rx;\r
+                       if ((ry+h) > vga_state.vga_height) h = vga_state.vga_height-ry;\r
+\r
+                       /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */\r
+                       vga_state.vga_draw_stride_limit = (vga_state.vga_width + 3/*round up*/ - x) >> 2;\r
+                       vga_state.vga_draw_stride = w >> 2;\r
+                       vga_state.vga_graphics_ram = omemptr + offscreen_ofs;\r
+\r
+                       /* first draw pattern corresponding to that part of the screen. this COULD be optimized, obviously, but it's designed for study.\r
+                        * also note we don't have to use the same stride as the display! */\r
+                       for (i=rx;i < (rx+w);i++) {\r
+                               o = (i-rx) >> 2;\r
+                               vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
+                               for (j=ry;j < (ry+h);j++,o += vga_state.vga_draw_stride)\r
+                                       vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
+                       }\r
+\r
+                       /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */\r
+                       draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));\r
+\r
+                       /* restore ptr */\r
+                       vga_state.vga_graphics_ram = omemptr;\r
+\r
+                       /* block copy to visible RAM from offscreen */\r
+                       vga_setup_wm1_block_copy();\r
+                       o = offscreen_ofs; // source offscreen\r
+                       o2 = (ry * vga_state.vga_stride) + (rx >> 2); // dest visible (original stride)\r
+                       for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);\r
+                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */\r
+                       vga_restore_rm0wm0();\r
+\r
+                       /* restore stride */\r
+                       vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride;\r
+\r
+                       /* step */\r
+                       x += xdir;\r
+                       y += ydir;\r
+                       if (x >= (vga_state.vga_width - 1) || x == 0)\r
+                               xdir = -xdir;\r
+                       if (y >= (vga_state.vga_height - 1) || y == 0)\r
+                               ydir = -ydir;\r
+               }\r
+       }\r
+\r
+       /* make distinctive pattern offscreen, render sprite, copy onscreen.\r
+        * this time, we render the distinctive pattern to another offscreen location and just copy.\r
+        * note this version is much faster too! */\r
+       {\r
+               const unsigned int offscreen_ofs = (vga_state.vga_stride * vga_state.vga_height);\r
+               const unsigned int pattern_ofs = 0x10000UL - (vga_state.vga_stride * vga_state.vga_height);\r
+               unsigned int i,j,o,o2,x,y,rx,ry,w,h;\r
+               unsigned int overdraw = 1;      // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks.\r
+                                               // if the sprite's edge pixels are clear anyway, you can set this to 0.\r
+               VGA_RAM_PTR omemptr;\r
+               int xdir=1,ydir=1;\r
+\r
+               /* fill pattern offset with a distinctive pattern */\r
+               for (i=0;i < vga_state.vga_width;i++) {\r
+                       o = (i >> 2) + pattern_ofs;\r
+                       vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
+                       for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride)\r
+                               vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
+               }\r
+\r
+               /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */\r
+               x = 0;\r
+               y = 0;\r
+\r
+               /* do it */\r
+               omemptr = vga_state.vga_graphics_ram; // save original mem ptr\r
+               while (1) {\r
+                       /* stop animating if the user hits ENTER */\r
+                       if (kbhit()) {\r
+                               if (getch() == 13) break;\r
+                       }\r
+\r
+                       /* render box bounds. y does not need modification, but x and width must be multiple of 4 */\r
+                       if (x >= overdraw) rx = (x - overdraw) & (~3);\r
+                       else rx = 0;\r
+                       if (y >= overdraw) ry = (y - overdraw);\r
+                       else ry = 0;\r
+                       h = vrl_header->height + overdraw + y - ry;\r
+                       w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3);\r
+                       if ((rx+w) > vga_state.vga_width) w = vga_state.vga_width-rx;\r
+                       if ((ry+h) > vga_state.vga_height) h = vga_state.vga_height-ry;\r
+\r
+                       /* block copy pattern to where we will draw the sprite */\r
+                       vga_setup_wm1_block_copy();\r
+                       o2 = offscreen_ofs;\r
+                       o = pattern_ofs + (ry * vga_state.vga_stride) + (rx >> 2); // source offscreen\r
+                       for (i=0;i < h;i++,o += vga_state.vga_stride,o2 += (w >> 2)) vga_wm1_mem_block_copy(o2,o,w >> 2);\r
+                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */\r
+                       vga_restore_rm0wm0();\r
+\r
+                       /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */\r
+                       vga_state.vga_draw_stride_limit = (vga_state.vga_width + 3/*round up*/ - x) >> 2;\r
+                       vga_state.vga_draw_stride = w >> 2;\r
+                       vga_state.vga_graphics_ram = omemptr + offscreen_ofs;\r
+\r
+                       /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */\r
+                       draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header));\r
+\r
+                       /* restore ptr */\r
+                       vga_state.vga_graphics_ram = omemptr;\r
+\r
+                       /* block copy to visible RAM from offscreen */\r
+                       vga_setup_wm1_block_copy();\r
+                       o = offscreen_ofs; // source offscreen\r
+                       o2 = (ry * vga_state.vga_stride) + (rx >> 2); // dest visible (original stride)\r
+                       for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2);\r
+                       /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */\r
+                       vga_restore_rm0wm0();\r
+\r
+                       /* restore stride */\r
+                       vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride;\r
+\r
+                       /* step */\r
+                       x += xdir;\r
+                       y += ydir;\r
+                       if (x >= (vga_state.vga_width - 1) || x == 0)\r
+                               xdir = -xdir;\r
+                       if (y >= (vga_state.vga_height - 1) || y == 0)\r
+                               ydir = -ydir;\r
+               }\r
+       }\r
+\r
+       /* another handy "demo" effect using VGA write mode 1.\r
+        * we can take what's on screen and vertically squash it like an old analog TV set turning off. */\r
+       {\r
+               unsigned int blank_line_ofs = (vga_state.vga_stride * vga_state.vga_height * 2);\r
+               unsigned int copy_ofs = (vga_state.vga_stride * vga_state.vga_height);\r
+               unsigned int display_ofs = 0x0000;\r
+               unsigned int i,y,soh,doh,dstart;\r
+               unsigned int dh_blankfill = 8;\r
+               unsigned int dh_step = 8;\r
+               uint32_t sh,dh,yf,ystep;\r
+\r
+               /* copy active display (0) to offscreen buffer (0x4000) */\r
+               vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride;\r
+               vga_setup_wm1_block_copy();\r
+               vga_wm1_mem_block_copy(copy_ofs,display_ofs,vga_state.vga_stride * vga_state.vga_height);\r
+               vga_restore_rm0wm0();\r
+\r
+               /* need a blank line as well */\r
+               for (i=0;i < vga_state.vga_stride;i++) vga_state.vga_graphics_ram[i+blank_line_ofs] = 0;\r
+\r
+               sh = dh = vga_state.vga_height;\r
+               while (dh >= dh_step) {\r
+                       /* stop animating if the user hits ENTER */\r
+                       if (kbhit()) {\r
+                               if (getch() == 13) break;\r
+                       }\r
+\r
+                       /* wait for vsync end */\r
+                       vga_wait_for_vsync_end();\r
+\r
+                       /* what scalefactor to use for stretching? */\r
+                       ystep = (0x10000UL * sh) / dh;\r
+                       dstart = (vga_state.vga_height - dh) / 2; // center the squash effect on screen, otherwise it would squash to top of screen\r
+                       doh = display_ofs;\r
+                       soh = copy_ofs;\r
+                       yf = 0;\r
+                       y = 0;\r
+\r
+                       /* for performance, keep VGA in write mode 1 the entire render */\r
+                       vga_setup_wm1_block_copy();\r
+\r
+                       /* blank lines */\r
+                       if (dstart >= dh_blankfill) y = dstart - dh_blankfill;\r
+                       else y = 0;\r
+                       doh = vga_state.vga_stride * y;\r
+\r
+                       while (y < dstart) {\r
+                               vga_wm1_mem_block_copy(doh,blank_line_ofs,vga_state.vga_stride);\r
+                               doh += vga_state.vga_stride;\r
+                               y++;\r
+                       }\r
+\r
+                       /* draw */\r
+                       while (y < (dh+dstart)) {\r
+                               soh = copy_ofs + ((yf >> 16UL) * vga_state.vga_stride);\r
+                               vga_wm1_mem_block_copy(doh,soh,vga_state.vga_stride);\r
+                               doh += vga_state.vga_stride;\r
+                               yf += ystep;\r
+                               y++;\r
+                       }\r
+\r
+                       /* blank lines */\r
+                       while (y < vga_state.vga_height && y < (dh+dstart+dh_blankfill)) {\r
+                               vga_wm1_mem_block_copy(doh,blank_line_ofs,vga_state.vga_stride);\r
+                               doh += vga_state.vga_stride;\r
+                               y++;\r
+                       }\r
+\r
+                       /* done */\r
+                       vga_restore_rm0wm0();\r
+\r
+                       /* wait for vsync */\r
+                       vga_wait_for_vsync();\r
+\r
+                       /* make it shrink */\r
+                       dh -= dh_step;\r
+                       if (dh < 40) dh_step = 1;\r
+               }\r
+       }\r
+\r
+       int10_setmode(3);\r
+       free(vrl_lineoffs);\r
+       buffer = NULL;\r
+       free(buffer);\r
+       bufsz = 0;\r
+       return 0;\r
+}\r
index dbe0bfc7e98182b72049236427bda12d48d2f39c..d1f8bbbe3ee54e1ec2fead4424e8a66ee3f89bf3 100755 (executable)
@@ -1,20 +1,20 @@
-#ifndef __TESUTO_H__
-#define __TESUTO_H__
-
-#include "src/lib/16_head.h"
-#include "src/lib/modex16.h"
-#include "src/lib/16_in.h"
-#include <hw/cpu/cpu.h>
-#include <hw/dos/dos.h>
-#include <hw/vga/vga.h>
-#include <hw/vga/vrl.h>
-
-typedef unsigned char far *VGA_RAM_PTR;
-//VGA_RAM_PTR vga_graphics_ram = (VGA_RAM_PTR)MK_FP(0xA000,0x0000);
-//unsigned char vga_stride = 80; // 80 x 4 = 320 for 320-pixel wide modes
-
-/*static inline void vga_write_sequencer(unsigned char i,unsigned char c) {
-    outp(0x3C4,i);
-    outp(0x3C5,c);
-}*/
-#endif
+#ifndef __TESUTO_H__\r
+#define __TESUTO_H__\r
+\r
+#include "src/lib/16_head.h"\r
+#include "src/lib/modex16.h"\r
+#include "src/lib/16_in.h"\r
+#include <hw/cpu/cpu.h>\r
+#include <hw/dos/dos.h>\r
+#include <hw/vga/vga.h>\r
+#include <hw/vga/vrl.h>\r
+\r
+typedef unsigned char far *VGA_RAM_PTR;\r
+//VGA_RAM_PTR vga_graphics_ram = (VGA_RAM_PTR)MK_FP(0xA000,0x0000);\r
+//unsigned char vga_stride = 80; // 80 x 4 = 320 for 320-pixel wide modes\r
+\r
+/*static inline void vga_write_sequencer(unsigned char i,unsigned char c) {\r
+    outp(0x3C4,i);\r
+    outp(0x3C5,c);\r
+}*/\r
+#endif\r
index 7476b7ea67db79d88b81547dfb4d5eb23461b369..245a5335831a4a928ecbaeb7a2bdf7330f491e2c 100755 (executable)
-/* tsthimem.c
- *
- * Test program: HIMEM.SYS functions
- * (C) 2010-2012 Jonathan Campbell.
- * Hackipedia DOS library.
- *
- * This code is licensed under the LGPL.
- * <insert LGPL legal text here>
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <conio.h>
-#include <dos.h>
-
-//#include "src/lib/doslib/cpu.h"
-#include "src/lib/doslib/dos.h"
-//#include doswin.h>
-#include "src/lib/doslib/himemsys.h"
-
-int main() {
-       probe_dos();
-       printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF);
-       /*if (detect_windows()) {
-               printf("I am running under Windows.\n");
-               printf("    Mode: %s\n",windows_mode_str(windows_mode));
-               printf("    Ver:  %x.%02u\n",windows_version>>8,windows_version&0xFF);
-       }
-       else {
-               printf("Not running under Windows or OS/2\n");
-       }*/
-
-       if (probe_himem_sys()) {
-               int h1,h2,h3;
-
-               printf("HIMEM.SYS detected. Entry point %04x:%04x. v%x.%02x\n",
-                               (unsigned int)((himem_sys_entry >> 16) & 0xFFFFUL),
-                               (unsigned int)(himem_sys_entry & 0xFFFFUL),
-                               (unsigned int)(himem_sys_version >> 8),
-                               (unsigned int)(himem_sys_version & 0xFF));
-
-               if (himem_sys_flags & HIMEM_F_HMA)
-                       printf("  - HMA is present\n");
-               if (himem_sys_flags & HIMEM_F_4GB)
-                       printf("  - Extensions are present to address up to 4GB of memory\n");
-
-               printf("A20 status: %u\n",himem_sys_query_a20());
-               printf("Global A20 line:         "); fflush(stdout);
-               printf("en=%d ",himem_sys_global_a20(1)); fflush(stdout);
-               printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout);
-               printf("dis=%d ",himem_sys_global_a20(0)); fflush(stdout);
-               printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout);
-               printf("\n");
-
-               printf("Local A20 line:          "); fflush(stdout);
-               printf("en=%d ",himem_sys_local_a20(1)); fflush(stdout);
-               printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout);
-               printf("dis=%d ",himem_sys_local_a20(0)); fflush(stdout);
-               printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout);
-               printf("\n");
-
-               himem_sys_update_free_memory_status();
-               printf("Free memory: %luKB (largest block %luKB)\n",
-                       (unsigned long)himem_sys_total_free,
-                       (unsigned long)himem_sys_largest_free);
-
-               printf("Attempting to alloc 4KB: ");
-               h1 = himem_sys_alloc(4); /* NTS: This is in KB, not bytes */
-               if (h1 != -1) printf("ok, handle %u\n",h1);
-               else printf("failed\n");
-
-               printf("Attempting to alloc 64KB: ");
-               h2 = himem_sys_alloc(46); /* NTS: This is in KB, not bytes */
-               if (h2 != -1) printf("ok, handle %u\n",h2);
-               else printf("failed\n");
-
-               printf("Attempting to alloc 1MB: ");
-               h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */
-               if (h3 != -1) printf("ok, handle %u\n",h3);
-               else printf("failed\n");
-
-               if (h1 != -1) {
-                       if (!himem_sys_free(h1)) printf(" - Free failed\n");
-               }
-               if (h2 != -1) {
-                       if (!himem_sys_free(h2)) printf(" - Free failed\n");
-               }
-               if (h3 != -1) {
-                       if (!himem_sys_free(h3)) printf(" - Free failed\n");
-               }
-
-               printf("Attempting to alloc 1MB (for writing to): ");
-               h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */
-               if (h3 != -1) {
-                       uint32_t ofs;
-                       unsigned int i;
-                       struct himem_block_info binf;
-#if TARGET_MSDOS == 32
-                       char *msg;
-                       unsigned char *tmp;
-                       uint16_t tmpsel=0,msgsel=0;
-                       const char *msgref = "Testing 123 hello";
-#else
-                       unsigned char tmp[16];
-                       const char *msg = "Testing 123 hello";
-#endif
-
-#if TARGET_MSDOS == 32
-                       tmp = dpmi_alloc_dos(16,&tmpsel);
-                       if (tmp == NULL) abort();
-                       msg = dpmi_alloc_dos(strlen(msgref)+16,&msgsel);
-                       if (msg == NULL) abort();
-                       memcpy(msg,msgref,strlen(msgref)+1);
-#endif
-
-                       printf("ok, handle %u\n",h3);
-
-                       if (himem_sys_get_handle_info(h3,&binf)) {
-                               printf("Handle info:\n");
-                               printf("     Lock count=%u  Free handles=%u  Size=%luKB\n",
-                                       (unsigned int)binf.lock_count,
-                                       (unsigned int)binf.free_handles,
-                                       (unsigned long)binf.block_length_kb);
-                       }
-                       else {
-                               printf("Cannot get handle info\n");
-                       }
-
-#if TARGET_MSDOS == 32
-                       if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16))
-#else
-                       if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp)))
-#endif
-                               printf("Copy didn't work\n");
-
-                       for (i=0;i < 16;i += 2) {
-                               tmp[i+0] = 0x55;
-                               tmp[i+1] = 0xAA;
-                       }
-
-#if TARGET_MSDOS == 32
-                       if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16))
-#else
-                       if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp)))
-#endif
-                               printf("Copy didn't work\n");
-
-                       for (i=0;i < 16;i++) printf("%02x ",tmp[i]);
-                       printf("\n");
-
-                       ofs = himem_sys_lock(h3);
-                       if (ofs != 0UL) {
-                               printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs);
-                               if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n");
-                       }
-                       else {
-                               printf(" - Cannot lock\n");
-                       }
-
-                       printf("now resizing to 2MB\n");
-                       if (himem_sys_realloc(h3,2048)) {
-#if TARGET_MSDOS == 32
-                               if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16))
-#else
-                               if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp)))
-#endif
-                                       printf("Copy didn't work\n");
-
-                               for (i=0;i < 16;i++) printf("%02x ",tmp[i]);
-                               printf("\n");
-
-                               ofs = himem_sys_lock(h3);
-                               if (ofs != 0UL) {
-                                       printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs);
-                                       if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n");
-                               }
-                               else {
-                                       printf(" - Cannot lock\n");
-                               }
-                       }
-                       else {
-                               printf(" - Cannot realloc\n");
-                       }
-
-                       if (!himem_sys_free(h3)) printf(" - Free failed\n");
-
-#if TARGET_MSDOS == 32
-                       dpmi_free_dos(tmpsel); tmp=NULL;
-                       dpmi_free_dos(msgsel); msg=NULL;
-#endif
-               }
-               else printf("failed\n");
-
-               printf("Attempting to alloc 129MB (for writing to): ");
-               h3 = himem_sys_alloc(129UL * 1024UL); /* NTS: This is in KB, not bytes */
-               if (h3 != -1) {
-                       uint32_t ofs;
-                       unsigned int i;
-                       unsigned char tmp[16];
-                       struct himem_block_info binf;
-                       const char *msg = "Testing 123 hello";
-
-                       printf("ok, handle %u\n",h3);
-
-                       if (himem_sys_get_handle_info(h3,&binf)) {
-                               printf("Handle info:\n");
-                               printf("     Lock count=%u  Free handles=%u  Size=%luKB\n",
-                                       (unsigned int)binf.lock_count,
-                                       (unsigned int)binf.free_handles,
-                                       (unsigned long)binf.block_length_kb);
-                       }
-                       else {
-                               printf("Cannot get handle info\n");
-                       }
-
-#if TARGET_MSDOS == 32
-                       if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16))
-#else
-                       if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp)))
-#endif
-                               printf("Copy didn't work\n");
-
-                       for (i=0;i < 16;i += 2) {
-                               tmp[i+0] = 0x55;
-                               tmp[i+1] = 0xAA;
-                       }
-
-#if TARGET_MSDOS == 32
-                       if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16))
-#else
-                       if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp)))
-#endif
-                               printf("Copy didn't work\n");
-
-                       for (i=0;i < 16;i++) printf("%02x ",tmp[i]);
-                       printf("\n");
-
-                       ofs = himem_sys_lock(h3);
-                       if (ofs != 0UL) {
-                               printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs);
-                               if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n");
-                       }
-                       else {
-                               printf(" - Cannot lock\n");
-                       }
-
-                       printf("now resizing to 144MB\n");
-                       if (himem_sys_realloc(h3,144UL*1024UL)) {
-                               if (himem_sys_get_handle_info(h3,&binf)) {
-                                       printf("Handle info:\n");
-                                       printf("     Lock count=%u  Free handles=%u  Size=%luKB\n",
-                                               (unsigned int)binf.lock_count,
-                                               (unsigned int)binf.free_handles,
-                                               (unsigned long)binf.block_length_kb);
-                               }
-                               else {
-                                       printf("Cannot get handle info\n");
-                               }
-
-#if TARGET_MSDOS == 32
-                               if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16))
-#else
-                               if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp)))
-#endif
-                                       printf("Copy didn't work\n");
-
-                               for (i=0;i < 16;i++) printf("%02x ",tmp[i]);
-                               printf("\n");
-
-                               ofs = himem_sys_lock(h3);
-                               if (ofs != 0UL) {
-                                       printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs);
-                                       if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n");
-                               }
-                               else {
-                                       printf(" - Cannot lock\n");
-                               }
-                       }
-                       else {
-                               printf(" - Cannot realloc\n");
-                       }
-
-                       if (!himem_sys_free(h3)) printf(" - Free failed\n");
-               }
-               else printf("failed\n");
-       }
-       else {
-               printf("HIMEM.SYS not found\n");
-       }
-
-       return 0;
-}
-
+/* tsthimem.c\r
+ *\r
+ * Test program: HIMEM.SYS functions\r
+ * (C) 2010-2012 Jonathan Campbell.\r
+ * Hackipedia DOS library.\r
+ *\r
+ * This code is licensed under the LGPL.\r
+ * <insert LGPL legal text here>\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <conio.h>\r
+#include <dos.h>\r
+\r
+//#include "src/lib/doslib/cpu.h"\r
+#include "src/lib/doslib/dos.h"\r
+//#include doswin.h>\r
+#include "src/lib/doslib/himemsys.h"\r
+\r
+int main() {\r
+       probe_dos();\r
+       printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF);\r
+       /*if (detect_windows()) {\r
+               printf("I am running under Windows.\n");\r
+               printf("    Mode: %s\n",windows_mode_str(windows_mode));\r
+               printf("    Ver:  %x.%02u\n",windows_version>>8,windows_version&0xFF);\r
+       }\r
+       else {\r
+               printf("Not running under Windows or OS/2\n");\r
+       }*/\r
+\r
+       if (probe_himem_sys()) {\r
+               int h1,h2,h3;\r
+\r
+               printf("HIMEM.SYS detected. Entry point %04x:%04x. v%x.%02x\n",\r
+                               (unsigned int)((himem_sys_entry >> 16) & 0xFFFFUL),\r
+                               (unsigned int)(himem_sys_entry & 0xFFFFUL),\r
+                               (unsigned int)(himem_sys_version >> 8),\r
+                               (unsigned int)(himem_sys_version & 0xFF));\r
+\r
+               if (himem_sys_flags & HIMEM_F_HMA)\r
+                       printf("  - HMA is present\n");\r
+               if (himem_sys_flags & HIMEM_F_4GB)\r
+                       printf("  - Extensions are present to address up to 4GB of memory\n");\r
+\r
+               printf("A20 status: %u\n",himem_sys_query_a20());\r
+               printf("Global A20 line:         "); fflush(stdout);\r
+               printf("en=%d ",himem_sys_global_a20(1)); fflush(stdout);\r
+               printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout);\r
+               printf("dis=%d ",himem_sys_global_a20(0)); fflush(stdout);\r
+               printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout);\r
+               printf("\n");\r
+\r
+               printf("Local A20 line:          "); fflush(stdout);\r
+               printf("en=%d ",himem_sys_local_a20(1)); fflush(stdout);\r
+               printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout);\r
+               printf("dis=%d ",himem_sys_local_a20(0)); fflush(stdout);\r
+               printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout);\r
+               printf("\n");\r
+\r
+               himem_sys_update_free_memory_status();\r
+               printf("Free memory: %luKB (largest block %luKB)\n",\r
+                       (unsigned long)himem_sys_total_free,\r
+                       (unsigned long)himem_sys_largest_free);\r
+\r
+               printf("Attempting to alloc 4KB: ");\r
+               h1 = himem_sys_alloc(4); /* NTS: This is in KB, not bytes */\r
+               if (h1 != -1) printf("ok, handle %u\n",h1);\r
+               else printf("failed\n");\r
+\r
+               printf("Attempting to alloc 64KB: ");\r
+               h2 = himem_sys_alloc(46); /* NTS: This is in KB, not bytes */\r
+               if (h2 != -1) printf("ok, handle %u\n",h2);\r
+               else printf("failed\n");\r
+\r
+               printf("Attempting to alloc 1MB: ");\r
+               h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */\r
+               if (h3 != -1) printf("ok, handle %u\n",h3);\r
+               else printf("failed\n");\r
+\r
+               if (h1 != -1) {\r
+                       if (!himem_sys_free(h1)) printf(" - Free failed\n");\r
+               }\r
+               if (h2 != -1) {\r
+                       if (!himem_sys_free(h2)) printf(" - Free failed\n");\r
+               }\r
+               if (h3 != -1) {\r
+                       if (!himem_sys_free(h3)) printf(" - Free failed\n");\r
+               }\r
+\r
+               printf("Attempting to alloc 1MB (for writing to): ");\r
+               h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */\r
+               if (h3 != -1) {\r
+                       uint32_t ofs;\r
+                       unsigned int i;\r
+                       struct himem_block_info binf;\r
+#if TARGET_MSDOS == 32\r
+                       char *msg;\r
+                       unsigned char *tmp;\r
+                       uint16_t tmpsel=0,msgsel=0;\r
+                       const char *msgref = "Testing 123 hello";\r
+#else\r
+                       unsigned char tmp[16];\r
+                       const char *msg = "Testing 123 hello";\r
+#endif\r
+\r
+#if TARGET_MSDOS == 32\r
+                       tmp = dpmi_alloc_dos(16,&tmpsel);\r
+                       if (tmp == NULL) abort();\r
+                       msg = dpmi_alloc_dos(strlen(msgref)+16,&msgsel);\r
+                       if (msg == NULL) abort();\r
+                       memcpy(msg,msgref,strlen(msgref)+1);\r
+#endif\r
+\r
+                       printf("ok, handle %u\n",h3);\r
+\r
+                       if (himem_sys_get_handle_info(h3,&binf)) {\r
+                               printf("Handle info:\n");\r
+                               printf("     Lock count=%u  Free handles=%u  Size=%luKB\n",\r
+                                       (unsigned int)binf.lock_count,\r
+                                       (unsigned int)binf.free_handles,\r
+                                       (unsigned long)binf.block_length_kb);\r
+                       }\r
+                       else {\r
+                               printf("Cannot get handle info\n");\r
+                       }\r
+\r
+#if TARGET_MSDOS == 32\r
+                       if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16))\r
+#else\r
+                       if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp)))\r
+#endif\r
+                               printf("Copy didn't work\n");\r
+\r
+                       for (i=0;i < 16;i += 2) {\r
+                               tmp[i+0] = 0x55;\r
+                               tmp[i+1] = 0xAA;\r
+                       }\r
+\r
+#if TARGET_MSDOS == 32\r
+                       if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16))\r
+#else\r
+                       if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp)))\r
+#endif\r
+                               printf("Copy didn't work\n");\r
+\r
+                       for (i=0;i < 16;i++) printf("%02x ",tmp[i]);\r
+                       printf("\n");\r
+\r
+                       ofs = himem_sys_lock(h3);\r
+                       if (ofs != 0UL) {\r
+                               printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs);\r
+                               if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n");\r
+                       }\r
+                       else {\r
+                               printf(" - Cannot lock\n");\r
+                       }\r
+\r
+                       printf("now resizing to 2MB\n");\r
+                       if (himem_sys_realloc(h3,2048)) {\r
+#if TARGET_MSDOS == 32\r
+                               if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16))\r
+#else\r
+                               if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp)))\r
+#endif\r
+                                       printf("Copy didn't work\n");\r
+\r
+                               for (i=0;i < 16;i++) printf("%02x ",tmp[i]);\r
+                               printf("\n");\r
+\r
+                               ofs = himem_sys_lock(h3);\r
+                               if (ofs != 0UL) {\r
+                                       printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs);\r
+                                       if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n");\r
+                               }\r
+                               else {\r
+                                       printf(" - Cannot lock\n");\r
+                               }\r
+                       }\r
+                       else {\r
+                               printf(" - Cannot realloc\n");\r
+                       }\r
+\r
+                       if (!himem_sys_free(h3)) printf(" - Free failed\n");\r
+\r
+#if TARGET_MSDOS == 32\r
+                       dpmi_free_dos(tmpsel); tmp=NULL;\r
+                       dpmi_free_dos(msgsel); msg=NULL;\r
+#endif\r
+               }\r
+               else printf("failed\n");\r
+\r
+               printf("Attempting to alloc 129MB (for writing to): ");\r
+               h3 = himem_sys_alloc(129UL * 1024UL); /* NTS: This is in KB, not bytes */\r
+               if (h3 != -1) {\r
+                       uint32_t ofs;\r
+                       unsigned int i;\r
+                       unsigned char tmp[16];\r
+                       struct himem_block_info binf;\r
+                       const char *msg = "Testing 123 hello";\r
+\r
+                       printf("ok, handle %u\n",h3);\r
+\r
+                       if (himem_sys_get_handle_info(h3,&binf)) {\r
+                               printf("Handle info:\n");\r
+                               printf("     Lock count=%u  Free handles=%u  Size=%luKB\n",\r
+                                       (unsigned int)binf.lock_count,\r
+                                       (unsigned int)binf.free_handles,\r
+                                       (unsigned long)binf.block_length_kb);\r
+                       }\r
+                       else {\r
+                               printf("Cannot get handle info\n");\r
+                       }\r
+\r
+#if TARGET_MSDOS == 32\r
+                       if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16))\r
+#else\r
+                       if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp)))\r
+#endif\r
+                               printf("Copy didn't work\n");\r
+\r
+                       for (i=0;i < 16;i += 2) {\r
+                               tmp[i+0] = 0x55;\r
+                               tmp[i+1] = 0xAA;\r
+                       }\r
+\r
+#if TARGET_MSDOS == 32\r
+                       if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16))\r
+#else\r
+                       if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp)))\r
+#endif\r
+                               printf("Copy didn't work\n");\r
+\r
+                       for (i=0;i < 16;i++) printf("%02x ",tmp[i]);\r
+                       printf("\n");\r
+\r
+                       ofs = himem_sys_lock(h3);\r
+                       if (ofs != 0UL) {\r
+                               printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs);\r
+                               if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n");\r
+                       }\r
+                       else {\r
+                               printf(" - Cannot lock\n");\r
+                       }\r
+\r
+                       printf("now resizing to 144MB\n");\r
+                       if (himem_sys_realloc(h3,144UL*1024UL)) {\r
+                               if (himem_sys_get_handle_info(h3,&binf)) {\r
+                                       printf("Handle info:\n");\r
+                                       printf("     Lock count=%u  Free handles=%u  Size=%luKB\n",\r
+                                               (unsigned int)binf.lock_count,\r
+                                               (unsigned int)binf.free_handles,\r
+                                               (unsigned long)binf.block_length_kb);\r
+                               }\r
+                               else {\r
+                                       printf("Cannot get handle info\n");\r
+                               }\r
+\r
+#if TARGET_MSDOS == 32\r
+                               if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16))\r
+#else\r
+                               if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp)))\r
+#endif\r
+                                       printf("Copy didn't work\n");\r
+\r
+                               for (i=0;i < 16;i++) printf("%02x ",tmp[i]);\r
+                               printf("\n");\r
+\r
+                               ofs = himem_sys_lock(h3);\r
+                               if (ofs != 0UL) {\r
+                                       printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs);\r
+                                       if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n");\r
+                               }\r
+                               else {\r
+                                       printf(" - Cannot lock\n");\r
+                               }\r
+                       }\r
+                       else {\r
+                               printf(" - Cannot realloc\n");\r
+                       }\r
+\r
+                       if (!himem_sys_free(h3)) printf(" - Free failed\n");\r
+               }\r
+               else printf("failed\n");\r
+       }\r
+       else {\r
+               printf("HIMEM.SYS not found\n");\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
index 0e9020d9e8607b4fbdb4f716c7926bed8303d9ef..cdba1e9b992999f492f47aad0f1402c2bb53c8bf 100755 (executable)
-/* Project 16 Source Code~
- * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdio.h>
-#include <dos.h>
-#include <string.h>
-#include "src/lib/modex16.h"
-#include "src/lib/16_sprit.h"
-#include "src/lib/16_ca.h"
-#include "src/lib/16_mm.h"
-
-void main() {
-       global_game_variables_t gvar;
-       __segment sega;
-       memptr bigbuffer;
-       int i;
-       word start;
-       int plane;
-       float t1, t2;
-       boolean baka;
-       byte *pal;
-       int size, size1;
-       struct sprite spri;
-       vrl1_vgax_offset_t * off, *off1;
-       struct vrs_container vrs;
-       vrl1_vgax_offset_t **vrl_line_offsets;
-       uint32_t huge *vrl_headers_offsets;
-       uint16_t huge *vrl_id_iter;
-       uint32_t vrl_size;
-       int num_of_vrl;
-       struct vrl1_vgax_header huge *curr_vrl;
-       struct vrl_container *vrl;
-       word w=0;
-
-       // DOSLIB: check our environment
-       probe_dos();
-
-       // DOSLIB: what CPU are we using?
-       // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS.
-       //      So this code by itself shouldn't care too much what CPU it's running on. Except that other
-       //      parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for
-       //      the CPU to carry out tasks. --J.C.
-       cpu_probe();
-
-       // DOSLIB: check for VGA
-       if (!probe_vga()) {
-               printf("VGA probe failed\n");
-               return;
-       }
-       // hardware must be VGA or higher!
-       if (!(vga_state.vga_flags & VGA_IS_VGA)) {
-               printf("This program requires VGA or higher graphics hardware\n");
-               return;
-       }
-
-       //gvar.video.page[0]=modexDefaultPage(&gvar.video.page[0]);
-
-       gvar.mm.mmstarted=0;
-       MM_Startup(&gvar.mm, &gvar.mmi);
-       CA_Startup(&gvar);
-       // What should be done by read_vrs:
-       //sega = (mm.bufferseg);
-       if(CA_LoadFile("data/spri/chikyuu.vrs", &bigbuffer, &gvar)) baka=1; else baka=0;
-
-       // Insert sanity cheks later
-       vrs.buffer = bigbuffer;
-       vrs.data_size = size - sizeof(struct vrl1_vgax_header);
-       num_of_vrl = 0;
-       vrl_id_iter = (uint16_t huge *)(vrs.buffer + vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]);
-       while(vrl_id_iter[num_of_vrl]){
-               num_of_vrl++;
-       }
-
-       // Allocate memory for vrl line offsets table
-       vrl_line_offsets = malloc(sizeof(vrl1_vgax_offset_t *)*num_of_vrl);
-
-       vrl_headers_offsets = (uint32_t huge *)(vrs.buffer + vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]);
-       // Calculate line offsets for each vrl
-       for(i = 0; i < num_of_vrl; i++){
-               curr_vrl = (struct vrl1_vgax_header huge *)(vrs.buffer + vrl_headers_offsets[i]);
-
-               // Calc. vrl size as (next_offset - curr_offset)
-               if (i != num_of_vrl - 1){
-                       vrl_size = vrl_headers_offsets[i+1] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header);
-               }
-               // If it's the last vrl, size is (next_vrs_struct_offset - curr_offset)
-               else{
-                       vrl_size = vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header);
-               }
-               vrl_line_offsets[i] = vrl1_vgax_genlineoffsets(curr_vrl, (byte *)curr_vrl + sizeof(struct vrl1_vgax_header), vrl_size);
-       }
-       vrs.vrl_line_offsets = vrl_line_offsets;
-
-
-       //read_vrs(&gvar, "data/spri/chikyuu.vrs", &vrs);
-       spri.spritesheet = &vrs;
-       spri.sprite_vrl_cont = malloc(sizeof(struct vrl_container));
-       i = set_anim_by_id(&spri, 11);
-       if (i == -1)
-       {
-               return;
-       }
-       spri.x = 5;
-       spri.y = 100;
-
-//     Uncomment to see broken sprites
-/*     sega = mm.bufferseg;
-       if(CA_LoadFile("data/spri/CHUBACW1.vrl", &bigbuffer, &mm, &mmi)) baka=1; else baka=0;*/
-
-       /* clear and draw one sprite and one bitmap */
-       VGAmodeX(1, 1, &gvar);
-       modexHiganbanaPageSetup(&gvar.video);
-
-       /* non sprite comparison */
-       start = *clockw;
-       modexCopyPageRegion(&gvar.video.page[0], &gvar.video.page[0], 0, 0, 0, 0, 320, 240);
-       t1 = (*clockw-start) /18.2;
-
-       start = *clockw;
-
-       t2 = (*clockw-start)/18.2;
-
-       for (i = 0; i < 5; i++){
-       spri.delay = 1; animate_spri(&spri); spri.x += 20; sleep(1); }
-
-       while(!kbhit())
-       {
-               switch(w)
-               {
-                       case 1024:
-                               modexPalUpdate0(pal);
-                               w=0;
-                       default:
-                               w++;
-                       break;
-               }
-       }
-       VGAmodeX(0, 1, &gvar);
-       MM_ShowMemory(&gvar, &gvar.mm);
-       MM_DumpData(&gvar.mm);
-       free(spri.sprite_vrl_cont);
-       MM_FreePtr(&bigbuffer, &gvar.mm);
-       //MM_FreePtr(&((void __based(sega)*)spri.spritesheet->buffer), &mm);
-       CA_Shutdown(&gvar);
-       MM_Shutdown(&gvar.mm);
-       //printf("CPU to VGA: %f\n", t1);
-       //printf("VGA to VGA: %f\n", t2);
-       heapdump(&gvar);
-       printf("Project 16 vrstest.exe. This is just a test file!\n");
-       printf("version %s\n", VERSION);
-       printf("t1: %f\n", t1);
-       printf("t2: %f\n", t2);
-       printf("gvar.video.page[0].width: %u\n", gvar.video.page[0].width);
-       printf("gvar.video.page[0].height: %u\n", gvar.video.page[0].height);
-       printf("Num %d", num_of_vrl);
-       if(baka) printf("\nyay!\n");
-       else printf("\npoo!\n");
-}
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "src/lib/modex16.h"\r
+#include "src/lib/16_sprit.h"\r
+#include "src/lib/16_tail.h"\r
+#include "src/lib/16_pm.h"\r
+#include "src/lib/16_ca.h"\r
+#include "src/lib/16_mm.h"\r
+\r
+void main() {\r
+       static global_game_variables_t gvar;\r
+       __segment sega;\r
+       memptr bigbuffer;\r
+       int i;\r
+       word start;\r
+       float t1, t2;\r
+       boolean baka;\r
+       byte *pal;\r
+       int size;\r
+       struct sprite spri;\r
+       vrl1_vgax_offset_t * off, *off1;\r
+       struct vrs_container vrs;\r
+       vrl1_vgax_offset_t **vrl_line_offsets;\r
+       uint32_t huge *vrl_headers_offsets;\r
+       uint16_t huge *vrl_id_iter;\r
+       uint32_t vrl_size;\r
+       int num_of_vrl;\r
+       struct vrl1_vgax_header huge *curr_vrl;\r
+       word w=0;\r
+\r
+       gvar.mm.mmstarted=0;\r
+       dbg_debugpm=1;\r
+\r
+       // DOSLIB: check our environment\r
+       probe_dos();\r
+\r
+       // DOSLIB: what CPU are we using?\r
+       // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS.\r
+       //      So this code by itself shouldn't care too much what CPU it's running on. Except that other\r
+       //      parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for\r
+       //      the CPU to carry out tasks. --J.C.\r
+       cpu_probe();\r
+\r
+       // DOSLIB: check for VGA\r
+       if (!probe_vga()) {\r
+               printf("VGA probe failed\n");\r
+               return;\r
+       }\r
+       // hardware must be VGA or higher!\r
+       if (!(vga_state.vga_flags & VGA_IS_VGA)) {\r
+               printf("This program requires VGA or higher graphics hardware\n");\r
+               return;\r
+       }\r
+\r
+       //gvar.video.page[0]=modexDefaultPage(&gvar.video.page[0]);\r
+\r
+       MM_Startup(&gvar);\r
+       PM_Startup(&gvar);\r
+       PM_UnlockMainMem(&gvar);\r
+       CA_Startup(&gvar);\r
+       // What should be done by read_vrs:\r
+       //sega = (mm.bufferseg);\r
+       if(CA_LoadFile("data/spri/chikyuu.vrs", &bigbuffer, &gvar)) baka=1; else baka=0;\r
+\r
+       // Insert sanity cheks later\r
+       vrs.buffer = bigbuffer;\r
+       vrs.data_size = size - sizeof(struct vrl1_vgax_header);\r
+       num_of_vrl = 0;\r
+       vrl_id_iter = (uint16_t huge *)(vrs.buffer + vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]);\r
+       while(vrl_id_iter[num_of_vrl]){\r
+               num_of_vrl++;\r
+       }\r
+\r
+       // Allocate memory for vrl line offsets table\r
+       vrl_line_offsets = malloc(sizeof(vrl1_vgax_offset_t *)*num_of_vrl);\r
+\r
+       vrl_headers_offsets = (uint32_t huge *)(vrs.buffer + vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]);\r
+       // Calculate line offsets for each vrl\r
+       for(i = 0; i < num_of_vrl; i++){\r
+               curr_vrl = (struct vrl1_vgax_header huge *)(vrs.buffer + vrl_headers_offsets[i]);\r
+\r
+               // Calc. vrl size as (next_offset - curr_offset)\r
+               if (i != num_of_vrl - 1){\r
+                       vrl_size = vrl_headers_offsets[i+1] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header);\r
+               }\r
+               // If it's the last vrl, size is (next_vrs_struct_offset - curr_offset)\r
+               else{\r
+                       vrl_size = vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header);\r
+               }\r
+               vrl_line_offsets[i] = vrl1_vgax_genlineoffsets(curr_vrl, (byte *)curr_vrl + sizeof(struct vrl1_vgax_header), vrl_size);\r
+       }\r
+       vrs.vrl_line_offsets = vrl_line_offsets;\r
+\r
+\r
+       //read_vrs(&gvar, "data/spri/chikyuu.vrs", &vrs);\r
+       spri.spritesheet = &vrs;\r
+       spri.sprite_vrl_cont = malloc(sizeof(struct vrl_container));\r
+       i = set_anim_by_id(&spri, 11);\r
+       if (i == -1)\r
+       {\r
+               return;\r
+       }\r
+       spri.x = 5;\r
+       spri.y = 100;\r
+\r
+//     Uncomment to see broken sprites\r
+/*     sega = mm.bufferseg;\r
+       if(CA_LoadFile("data/spri/CHUBACW1.vrl", &bigbuffer, &mm, &mmi)) baka=1; else baka=0;*/\r
+\r
+       /* clear and draw one sprite and one bitmap */\r
+       VGAmodeX(1, 1, &gvar);\r
+       modexHiganbanaPageSetup(&gvar.video);\r
+\r
+       /* non sprite comparison */\r
+       start = *clockw;\r
+       modexCopyPageRegion(&gvar.video.page[0], &gvar.video.page[0], 0, 0, 0, 0, 320, 240);\r
+       t1 = (*clockw-start) /18.2;\r
+\r
+       start = *clockw;\r
+\r
+       t2 = (*clockw-start)/18.2;\r
+\r
+       for (i = 0; i < 5; i++){\r
+       spri.delay = 1; animate_spri(&spri); spri.x += 20; /*sleep(1);*/ }\r
+\r
+       while(!kbhit())\r
+       {\r
+               switch(w)\r
+               {\r
+                       case 1024:\r
+                               modexPalUpdate0(pal);\r
+                               w=0;\r
+                       default:\r
+                               w++;\r
+                       break;\r
+               }\r
+       }\r
+       VGAmodeX(0, 1, &gvar);\r
+       MM_ShowMemory(&gvar);\r
+       MM_DumpData(&gvar);\r
+       MM_Report_(&gvar);\r
+       free(spri.sprite_vrl_cont);\r
+       MM_FreePtr(&bigbuffer, &gvar);\r
+       //MM_FreePtr(&((void __based(sega)*)spri.spritesheet->buffer), &mm);\r
+       PM_Shutdown(&gvar);\r
+       CA_Shutdown(&gvar);\r
+       MM_Shutdown(&gvar);\r
+       //printf("CPU to VGA: %f\n", t1);\r
+       //printf("VGA to VGA: %f\n", t2);\r
+       heapdump(&gvar);\r
+       printf("Project 16 vrstest.exe. This is just a test file!\n");\r
+       printf("version %s\n", VERSION);\r
+       printf("t1: %f\n", t1);\r
+       printf("t2: %f\n", t2);\r
+//0000 printf("gvar.video.page[0].width: %u\n", gvar.video.page[0].width);\r
+//0000 printf("gvar.video.page[0].height: %u\n", gvar.video.page[0].height);\r
+       printf("Num %d", num_of_vrl);\r
+       if(baka) printf("\nyay!\n");\r
+       else printf("\npoo!\n");\r
+}\r
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3162336759841b37722be8febc8497033898c6a3 100755 (executable)
@@ -0,0 +1,302 @@
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "src/lib/scroll16.h"\r
+#include "src/lib/16_timer.h"\r
+#include "src/lib/wcpu/wcpu.h"\r
+\r
+//word far *clock= (word far*) 0x046C; /* 18.2hz clock */\r
+//bitmap_t *p;\r
+global_game_variables_t gvar;\r
+static map_t map;\r
+player_t player[MaxPlayers];\r
+map_view_t mv[4];\r
+//word pn=0; //i forgot ww\r
+float t;\r
+sword bakapee;\r
+pan_t pan;\r
+//debugswitches\r
+boolean panswitch=0,baka=0;\r
+//extern boolean pageflipflop=1;\r
+       unsigned int i;\r
+       const char *cpus;\r
+       //static int persist_aniframe = 0;    /* gonna be increased to 1 before being used, so 0 is ok for default */\r
+\r
+       //map_view_db_t pgid[4];\r
+       word pg;\r
+//#ifdef FADE\r
+       static word paloffset=0;\r
+       byte *dpal;\r
+//#endif\r
+       byte *gpal;\r
+       byte *ptr;\r
+       byte *mappalptr;\r
+\r
+void main(int argc, char *argv[])\r
+{\r
+       byte *mesg=malloc(sizeof(dword));\r
+\r
+       if(argv[1]) bakapee = atoi(argv[1]);\r
+       else bakapee = 1;\r
+\r
+       Startup16(&gvar);\r
+\r
+       pan.pn=1;\r
+\r
+       /* create the map */\r
+       fprintf(stderr, "testing map load~      ");\r
+       loadmap("data/test.map", &map);\r
+       chkmap(&map, 0);\r
+       printf("chkmap ok       ");\r
+       fprintf(stderr, "yay map loaded~~\n");\r
+\r
+       /* draw the tiles */\r
+       ptr = map.data;\r
+       //mappalptr = map.tiles->btdata->palette;\r
+\r
+       /* data */\r
+       if(CA_LoadFile("data/spri/chikyuu.vrs", &(player[0].gr), &gvar)) baka=1; else baka=0;\r
+\r
+       /* create the planar buffer */\r
+////++++       (player[0].data) = *planar_buf_from_bitmap(&p);\r
+       /*++++printf("load pee!!        ");\r
+       pp = planar_buf_from_bitmap(&p);\r
+       printf("done!\n");*/\r
+\r
+       /*      input!  */\r
+       IN_Default(0,&player,ctrl_Joystick);\r
+       //IN_Default(1,&player,ctrl_Joystick);\r
+\r
+       /* save the palette */\r
+       dpal = modexNewPal();\r
+       modexPalSave(dpal);\r
+       modexFadeOff(4, dpal);\r
+\r
+       textInit();\r
+       VGAmodeX(bakapee, 1, &gvar);\r
+//     printf("%dx%d\n", gvar.video.page[0].sw, gvar.video.page[0].sh);\r
+       modexPalBlack();        //reset the palette~\r
+\r
+//     printf("Total used @ before palette initiation:         %zu\n", oldfreemem-GetFreeSize());\r
+//++++ player[0].data.offset=(paloffset/3);\r
+//++++ modexPalUpdate1(&player[0].data, &paloffset, 0, 0);\r
+               modexPalUpdate1(player[0].data->palette);\r
+//++++0000             modexPalUpdate1(map.tiles->btdata->palette);\r
+       //printf("      %d\n", sizeof(ptmp->data));\r
+       //printf("1:    %d\n", paloffset);\r
+//++++ map.tiles->data->offset=(paloffset/3);\r
+       //XTmodexPalUpdate(map.tiles->data, &paloffset, 0, 0);\r
+//     printf("\n====\n");\r
+//     printf("0       paloffset=      %d\n", paloffset/3);\r
+//     printf("====\n\n");\r
+\r
+       gpal = modexNewPal();\r
+       modexPalSave(gpal);\r
+       modexSavePalFile("data/g.pal", gpal);\r
+       modexPalBlack();        //so player will not see loadings~\r
+\r
+       /* setup camera and screen~ */\r
+       modexHiganbanaPageSetup(&gvar.video);\r
+       for(i=0;i<gvar.video.num_of_pages;i++)\r
+       {\r
+               mv[i].page = &gvar.video.page[i];\r
+               mv[i].map = &map;\r
+               mv[i].video = &gvar.video;\r
+               mv[i].pan       = &pan;\r
+       }\r
+\r
+       /* set up paging */\r
+       //TODO: LOAD map data and position the map in the middle of the screen if smaller then screen\r
+       mapGoTo(mv, 0, 0);\r
+       //_fmemcpy(mv[1].page->data, mv[0].page->data, mv[0].page->pagesize);\r
+\r
+       //TODO: put player in starting position of spot\r
+       //default player position on the viewable map\r
+       player[0].tx = mv[0].tx + mv[0].page->tilemidposscreenx;\r
+       player[0].ty = mv[0].ty + mv[0].page->tilemidposscreeny;\r
+       IN_initplayer(&player, 0);\r
+       //IN_initplayer(&player, 1);\r
+\r
+#ifndef        SPRITE\r
+       modexClearRegion(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);\r
+       //modexClearRegion(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 32, 15);\r
+#else\r
+       //PBUFSFUN(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 64, 24, 32, PLAYERBMPDATA);\r
+       PBUFSFUN(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 64, 16, 32,   player[0].data);\r
+#endif\r
+\r
+       if(!pageflipflop)       modexShowPage(mv[1].page);\r
+       else                    modexShowPage(mv[0].page);//!(gvar.video.p)\r
+               shinku_fps_indicator_page = 0; // we're on page 1 now, shinku(). follow along please or it will not be visible.\r
+\r
+       /* buffer pages */\r
+//     modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 47);\r
+//     modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 45);\r
+//     {\r
+//             unsigned int k,j,o;\r
+//             /* fill screen with a distinctive pattern */\r
+//             for (k=0;k < vga_state.vga_width;k++) {\r
+//                     o = k >> 2;\r
+//                     vga_write_sequencer(0x02/*map mask*/,1 << (k&3));\r
+//                             for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride)\r
+//                                     vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15!\r
+//             }\r
+//     }\r
+       modexClearRegion(mv[3].page, 0, 128, 24, 36, 15);\r
+\r
+       modexFadeOn(4, gpal);\r
+       while(!IN_KeyDown(sc_Escape) && player[0].hp>0)\r
+       {\r
+               shinku(&gvar);\r
+       //top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square\r
+       //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction\r
+       //when player[0].tx or player[0].ty == 0 or player[0].tx == 20 or player[0].ty == 15 then stop because that is edge of map and you do not want to walk of the map\r
+\r
+       //player movement\r
+               IN_ReadControl(0,&player);\r
+       if(!panswitch){\r
+               walk(mv, player, 0);\r
+       }else{\r
+               panpagemanual(mv, player, 0);\r
+               //printf("      player[0].q: %d", player[0].q); printf("        player[0].d: %d\n", player[0].d);\r
+       }\r
+\r
+       //the scripting stuff....\r
+       //if(((player[0].triggerx == TRIGGX && player[0].triggery == TRIGGY) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))\r
+       if(((mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))] == 0) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5))\r
+       {\r
+               short i;\r
+               for(i=800; i>=400; i--)\r
+               {\r
+                       sound(i);\r
+               }\r
+               nosound();\r
+       }\r
+       if(player[0].q == (TILEWH/(player[0].speed))+1 && player[0].info.dir != 2 && (player[0].triggerx == 5 && player[0].triggery == 5)){ player[0].hp--; }\r
+       //debugging binds!\r
+       if(IN_KeyDown(2)){ modexShowPage(mv[0].page); pan.pn=0; }\r
+       if(IN_KeyDown(3)){ modexShowPage(mv[1].page); pan.pn=1; }\r
+       if(IN_KeyDown(4)){ modexShowPage(mv[2].page); pan.pn=2; }\r
+       if(IN_KeyDown(4+1)){ modexShowPage(mv[3].page); pan.pn=3; }\r
+       if(IN_KeyDown(25)){ modexpdump(mv[0].page); modexpdump(mv[1].page);\r
+                IN_UserInput(1,1);\r
+       }       //p\r
+       if(IN_KeyDown(24)){ modexPalUpdate0(gpal); paloffset=0; modexpdump(mv[0].page); modexpdump(mv[1].page);  IN_UserInput(1,1); }\r
+       if(IN_KeyDown(22)){\r
+       paloffset=0; modexPalBlack(); modexPalUpdate(player[0].data, &paloffset, 0, 0);\r
+       printf("2paloffset      =       %d\n", paloffset/3);\r
+        modexpdump(mv[0].page); modexpdump(mv[1].page);\r
+               IN_UserInput(1,1);\r
+       }\r
+\r
+       //pan switch\r
+       if(IN_KeyDown(88)){panswitch=!panswitch; IN_UserInput(1,1);}    //f12\r
+       if(IN_KeyDown(87))      //f11\r
+       {\r
+               pageflipflop=!pageflipflop;\r
+               IN_UserInput(1,1);\r
+//             VGAmodeX(0, 0, &gvar);\r
+//             IN_Shutdown();\r
+//             __asm\r
+//             {\r
+//                     mov ah,31h\r
+//                     int 21h\r
+//             }\r
+       }\r
+       if(IN_KeyDown(68))      //f10\r
+       {\r
+               gvar.kurokku.fpscap=!gvar.kurokku.fpscap;\r
+               IN_UserInput(1,1);\r
+       }\r
+       if(IN_KeyDown(67))      //f9\r
+       {\r
+               modexClearRegion(mv[1].page, 0, 0, mv[1].page->width, mv[1].page->height, 2);\r
+               modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 3);\r
+               modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 4);\r
+               modexClearRegion(mv[3].page, 0, 0, 20, 36, 15);\r
+               //IN_UserInput(1,1);\r
+       }\r
+       if(IN_KeyDown(66))      //f8\r
+       {\r
+//             modexDrawSprite(mv[0].page, 16, 16, p);\r
+               modexDrawSprite(mv[0].page, 32+48, 16, (player[0].data));\r
+       }\r
+       //TODO fmemtest into page\r
+       /*if(IN_KeyDown(4+1))   //4\r
+       {\r
+               pg=1;\r
+               SELECT_ALL_PLANES();\r
+               _fmemset(((mv[pg].page->data+4)+(16*(mv[pg].page->width/4))), 15, 4);\r
+       }*/\r
+\r
+       //9\r
+       if(IN_KeyDown(10)){ modexPalOverscan(rand()%56); modexPalUpdate1(dpal); IN_UserInput(1,1); }\r
+       //if(IN_KeyDown(11)){ modexPalOverscan(15); }\r
+       if((player[0].q==1) && !(player[0].x%TILEWH==0 && player[0].y%TILEWH==0)) break;        //incase things go out of sync!\r
+       }\r
+\r
+       /* fade back to text mode */\r
+       /* but 1st lets save the game palette~ */\r
+       modexPalSave(gpal);\r
+       modexSavePalFile("data/g.pal", gpal);\r
+       modexFadeOff(4, gpal);\r
+       VGAmodeX(0, 1, &gvar);\r
+       Shutdown16(&gvar);\r
+       printf("\nProject 16 scroll.exe. This is just a test file!\n");\r
+       printf("version %s\n", VERSION);\r
+       printf("tx: %d  ", mv[0].tx);\r
+       printf("ty: %d\n", mv[0].ty);\r
+       printf("\n");\r
+       printf("player vars:\n");\r
+       printf("        x: %d", player[0].x); printf("  y: %d\n", player[0].y);\r
+       //if(player[0].hp==0) printf("%d wwww\n", player[0].y+8);\r
+       //else printf("\nplayer[0].y: %d\n", player[0].y);\r
+       printf("        tx: %d", player[0].tx); printf("        ty: %d\n", player[0].ty);\r
+       printf("        triggx: %d", player[0].triggerx); printf("      triggy: %d\n", player[0].triggery);\r
+       printf("        hp: %d", (player[0].hp));       printf("        q: %d", player[0].q);   printf("        player.info.dir: %d", player[0].info.dir);      printf("        player.d: %d ", player[0].d);\r
+               printf("        pdir=%d\n", player[0].pdir);\r
+       printf("        tile data value at player trigger position: %d\n\n", mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))]);\r
+       printf("Virtual Screen: %dx", gvar.video.page[0].width);        printf("%d      ", gvar.video.page[0].height);\r
+       printf("Screen: %dx", gvar.video.page[0].sw);   printf("%d\n", gvar.video.page[0].sh);\r
+       printf("virtual tile resolution: %dx", gvar.video.page[0].tilesw);      printf("%d      ", gvar.video.page[0].tilesh);\r
+       printf("tile resolution: %dx", gvar.video.page[0].tw);  printf("%d\n", gvar.video.page[0].th);\r
+       printf("middle tile position: %dx", gvar.video.page[0].tilemidposscreenx);      printf("%d\n", gvar.video.page[0].tilemidposscreeny);\r
+       modexprintmeminfo(&gvar.video);\r
+       //printf("mv[%u].tx: %d", pan.pn, mv[pan.pn].tx); printf("      mv[%u].ty: %d   ", pan.pn, mv[pan.pn].ty);\r
+       printf("gvar.video.p=%u ", gvar.video.p); printf("gvar.video.r=%u ", gvar.video.r);\r
+       printf("pageflipflop=%u\n", pageflipflop);\r
+       //0000printf("\ngvar.video.tickclk=%f\n", gvar.video.tickclk);\r
+       //0000printf("gvar.video.clk=%f", gvar.video.clk);\r
+       printf("\n");\r
+       //printf("map.width=%d  map.height=%d   map.data[0]=%d\n", mv[0].map->width, mv[0].map->height, mv[0].map->data[0]);\r
+\r
+       printf("\n");\r
+       switch(detectcpu())\r
+       {\r
+               case 0: cpus = "8086/8088 or 186/88"; break;\r
+               case 1: cpus = "286"; break;\r
+               case 2: cpus = "386 or newer"; break;\r
+               default: cpus = "internal error"; break;\r
+       }\r
+       printf("detected CPU type: %s\n", cpus);\r
+       modexFadeOn(4, dpal);\r
+}\r
diff --git a/test.exe b/test.exe
new file mode 100755 (executable)
index 0000000..c26af16
Binary files /dev/null and b/test.exe differ
diff --git a/test0.exe b/test0.exe
new file mode 100755 (executable)
index 0000000..a8a34c9
Binary files /dev/null and b/test0.exe differ
diff --git a/vgmtest.exe b/vgmtest.exe
new file mode 100755 (executable)
index 0000000..d4aeea4
Binary files /dev/null and b/vgmtest.exe differ
diff --git a/wolf3dpm.png b/wolf3dpm.png
new file mode 100755 (executable)
index 0000000..2844456
Binary files /dev/null and b/wolf3dpm.png differ