/** VGB: portable GameBoy emulator ***************************/ /** **/ /** Amiga.c **/ /** **/ /** Amiga-specific graphics/joystick routines drivers. **/ /** **/ /** Copyright (C) Lars Malmborg 1996 **/ /** based on a version by Michael Boese & Matthias Bethke **/ /** and the Unix/X version. **/ /** **/ /** Copyright (C) Marat Fayzullin 1994,1995,1996 **/ /** Elan Feingold 1995 **/ /** You are not allowed to distribute this software **/ /** commercially. Please, notify me, if you make any **/ /** changes to this file. **/ /*************************************************************/ #define REVISION "rev. 2" #define USE_XPAL /* We are using XPal[] to determine colors */ /* Amiga includes */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CYBER #include #include #endif void __inline AllocatePens(void); #include "GB.h" #include "AmigaRawkeys.h" /** Various variables and short functions ********************/ #define WIDTH_OFFS 8 #define WIDTH (160+2*WIDTH_OFFS) #define HEIGHT 144 char *Title = "Virtual GameBoy 0.7"; char *AmigaVersion="$VER: Virtual GameBoy Amiga 0.7 "REVISION" "__AMIGADATE__; int ExitFlag = 0; byte *XBuf=NULL,*ZBuf=NULL; LONG XPal[12]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; struct Screen *scr=NULL; struct Window *win=NULL; struct RastPort *rp=NULL; char ReqText[]= "Virtual Gameboy V0.7 by\n\ Marat Fayzullin \n\ Amiga version "REVISION" "__AMIGADATE__" by\n\ Lars Malmborg \n\n\ In-game keys:\n\ Left Alt or '+' on key pad - 'A'\n\ Left Shift or '6' on key pad - 'B'\n\ Right Shift or '4' on key pad - 'Select'\n\ Return or '5' on key pad - 'Start'\n\ Cursorkeys - Joypad\n\n\ ESC - Quit emulation\n" #ifdef DEBUG "\ F1 - Go into built-in debugger\n\ F2 - Show LCD controller registers\n" F3 - Show sprite registers\n" #endif ; //Gremlins! struct EasyStruct HelpReq = { sizeof(struct EasyStruct), 0, "VGB Amiga Help", ReqText, "OK" }; #ifndef CYBER struct RastPort temprp; /* struct BitMap tempbm; char tempp[WIDTH*8]; */ #endif BOOL ScaleUp; STRPTR PubScreen; int InitMachine(void) { int scale; if (ScaleUp) scale=2; else scale=1; if (scr = LockPubScreen(PubScreen)) { if(win = OpenWindowTags(NULL, WA_Left,(scr->Width - scale*(WIDTH-2*WIDTH_OFFS))/2, WA_Top,(scr->Height - scale*HEIGHT)/2, WA_InnerWidth,scale*(WIDTH-2*WIDTH_OFFS), WA_InnerHeight,scale*HEIGHT, WA_Title,Title, WA_CloseGadget,TRUE, WA_DepthGadget,TRUE, WA_DragBar,TRUE, WA_SizeGadget,FALSE, WA_RMBTrap,TRUE, WA_Activate,TRUE, WA_IDCMP,IDCMP_RAWKEY|IDCMP_CLOSEWINDOW, WA_PubScreenName,PubScreen, TAG_END )) { UnlockPubScreen(PubScreen,scr); rp = win->RPort; AllocatePens(); if(!(XBuf=AllocVec(sizeof(byte)*HEIGHT*WIDTH,MEMF_ANY))) return(0); if(!(ZBuf=AllocVec(sizeof(byte)*2*WIDTH*HEIGHT/8,MEMF_ANY))) return(0); #ifndef CYBER // init temprp CopyMem(rp,&temprp,sizeof(struct RastPort)); temprp.Layer=NULL; if (!(temprp.BitMap=AllocBitMap(scale*(WIDTH-2*WIDTH_OFFS),1,rp->BitMap->Depth,0,NULL))) { fprintf(stderr,"Error allocating temporary rastport.\n"); return(0); } #endif } else { fprintf(stderr,"Can't open window.\n"); return(0); } } else { fprintf(stderr,"Screen not found.\n"); return(0); } return(1); } /** TrashMachine *********************************************/ /** Deallocate all resources taken by InitMachine(). **/ /*************************************************************/ void TrashMachine(void) { int i; #ifndef CYBER // release temprp if (temprp.BitMap) FreeBitMap(temprp.BitMap); #endif if (ZBuf) FreeVec(ZBuf); if (XBuf) FreeVec(XBuf); if (win) CloseWindow(win); for(i=0; i<12; i++) if (XPal[i]!=-1) ReleasePen(scr->ViewPort.ColorMap,XPal[i]); } /** PutImage *************************************************/ /** Put an image on the screen. **/ /*************************************************************/ void PutImage(void) { #ifdef CYBER // Render with cybergraphics.library int scale; if (ScaleUp) scale=2; else scale=1; WritePixelArray(XBuf,WIDTH_OFFS,0,scale*WIDTH,rp,win->BorderLeft,win->BorderTop,scale*(WIDTH-2*WIDTH_OFFS),HEIGHT,RECTFMT_LUT8); #else // Render with graphics.library if (ScaleUp) { register int i; for(i=0;i<144;i++) { UBYTE drawarray[2*(WIDTH-2*WIDTH_OFFS)]; register int n; for (n=0;n<(WIDTH-2*WIDTH_OFFS);n++) { drawarray[n*2]=(UBYTE)(XBuf[(i*WIDTH)+n+WIDTH_OFFS]); drawarray[n*2+1]=drawarray[n*2]; } WritePixelLine8(rp,win->BorderLeft,win->BorderTop+i*2,2*(WIDTH-2*WIDTH_OFFS),drawarray,&temprp); WritePixelLine8(rp,win->BorderLeft,win->BorderTop+i*2+1,2*(WIDTH-2*WIDTH_OFFS),drawarray,&temprp); } } else { register int i; for(i=0;i<144;i++) { WritePixelLine8(rp,win->BorderLeft,win->BorderTop+i,WIDTH-2*WIDTH_OFFS,(UBYTE*)(&XBuf[(i*WIDTH)+WIDTH_OFFS]),&temprp); } } } /** Joystick *************************************************/ /** Return the current joystick state. **/ /*************************************************************/ byte Joystick(void) { struct IntuiMessage *imsg; ULONG imsg_Class; UWORD Code; #ifdef DEBUG int J; #endif static byte JoyState=0xff; if(imsg = (struct IntuiMessage*)GetMsg(win->UserPort)) { imsg_Class = imsg->Class; Code = imsg->Code; ReplyMsg((struct Message*)imsg); switch(imsg_Class) { case IDCMP_CLOSEWINDOW: ExitFlag = 1; break; case IDCMP_RAWKEY: if(Code & 0x80) { switch(Code & 0x7f) { #ifdef DEBUG case KEY_F1: Trace=!Trace; break; case KEY_F2: puts("\n*** REGISTERS: ***"); //F2 up for(J=0xFF40;J<0xFF50;J++) printf("(%Xh) = %Xh\n",J,RAM[J]); printf("ISWITCH = %Xh\n",ISWITCH); break; case KEY_F3: puts("\n*** SPRITES: ***"); for(J=0xFE9C;J<0xFE9C+4*40;J+=4) printf("SPRITE %d: %d,%d Pat %d Attr %d\n",(J-0xFE9C)/4,RAM[J+1],RAM[J],RAM[J+2],RAM[J+3]); break; #endif case KEY_HELP: EasyRequestArgs(win,&HelpReq,NULL,NULL); break; case KEY_RETURN: //start case KEY_P5: JoyState|=0x80; break; case KEY_RSHIFT: //select case KEY_P4: JoyState|=0x40; break; case KEY_LSHIFT: //B case KEY_P6: JoyState|=0x20; break; case KEY_LALT: //A case KEY_PPLUS: JoyState|=0x10; break; case KEY_CDOWN: //Down JoyState|=0x08; break; case KEY_CUP: //Up JoyState|=0x04; break; case KEY_CLEFT: //Left JoyState|=0x02; break; case KEY_CRIGHT: //Right JoyState|=0x01; break; } } else { switch(Code) { case KEY_ESC: ExitFlag = 1; break; case KEY_RETURN: case KEY_P5: JoyState&=0x7F; break; case KEY_RSHIFT: case KEY_P4: JoyState&=0xBF; break; case KEY_LSHIFT: case KEY_P6: JoyState&=0xDF; break; case KEY_LALT: case KEY_PPLUS: JoyState&=0xEF; break; case KEY_CDOWN: JoyState&=0xF7; break; case KEY_CUP: JoyState&=0xFB; break; case KEY_CLEFT: JoyState&=0xFD; break; case KEY_CRIGHT: JoyState&=0xFE; break; } } break; } } if(ExitFlag) { TrashGB();TrashMachine();exit(0); } return(JoyState); } struct { LONG r,g,b; } GB_Colors[12]={ {0xff000000,0xff000000,0xff000000},{0x98000000,0x98000000,0x98000000}, {0x58000000,0x58000000,0x58000000},{0x00000000,0x00000000,0x00000000}, {0xff000000,0xff000000,0xff000000},{0x98000000,0x98000000,0x98000000}, {0x58000000,0x58000000,0x58000000},{0x00000000,0x00000000,0x00000000}, {0xff000000,0xff000000,0xff000000},{0x98000000,0x98000000,0x98000000}, {0x58000000,0x58000000,0x58000000},{0x00000000,0x00000000,0x00000000}}; void SetColors(int mode, char* color) { long tcol[4]; int i=0; while (!isdigit(color[i])) i++; sscanf(color,"%lx,%lx,%lx,%lx",&tcol[0],&tcol[1],&tcol[2],&tcol[3]); GB_Colors[mode+0].r=(tcol[0]&0x00ff0000)<<8; GB_Colors[mode+0].g=(tcol[0]&0x0000ff00)<<16; GB_Colors[mode+0].b=(tcol[0]&0x000000ff)<<24; GB_Colors[mode+1].r=(tcol[1]&0x00ff0000)<<8; GB_Colors[mode+1].g=(tcol[1]&0x0000ff00)<<16; GB_Colors[mode+1].b=(tcol[1]&0x000000ff)<<24; GB_Colors[mode+2].r=(tcol[2]&0x00ff0000)<<8; GB_Colors[mode+2].g=(tcol[2]&0x0000ff00)<<16; GB_Colors[mode+2].b=(tcol[2]&0x000000ff)<<24; GB_Colors[mode+3].r=(tcol[3]&0x00ff0000)<<8; GB_Colors[mode+3].g=(tcol[3]&0x0000ff00)<<16; GB_Colors[mode+3].b=(tcol[3]&0x000000ff)<<24; } void AllocatePens(void) { int i; for(i=0; i<12; i++) { XPal[i] = ObtainBestPenA(scr->ViewPort.ColorMap,GB_Colors[i].r,GB_Colors[i].g,GB_Colors[i].b,NULL); } } /*** SIOSend ****************************************************/ /*** Send a byte onto the serial line. ***/ /****************************************************************/ byte SIOSend(register byte V) { return(0); } /*** SIOReceive *************************************************/ /*** Receive a byte from the serial line. Returns 1 on ***/ /*** success, 0 otherwise. ***/ /****************************************************************/ byte SIOReceive(register byte *V) { return(0); } /****************************************************************/ /*** Write value into sound chip register (Reg #0 at FF10h). ***/ /****************************************************************/ void Sound(byte R,byte V) { return; } /** Common.h ****************************************************/ /** Parts of the drivers common for Unix/X and MSDOS. **/ /****************************************************************/ #include "Common.h"