home *** CD-ROM | disk | FTP | other *** search
- /*
- * gbe - gameboy emulator
- * Copyright (C) 1999 Chuck Mason, Steven Fuller
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * Chuck Mason <chuckjr@sinclair.net>
- * Steven Fuller <relnev@atdot.org>
- */
-
- #ifdef BUILD_AMIGA
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <string.h>
- #include <time.h>
- #include <ctype.h>
- #include <unistd.h>
- #include <signal.h>
-
- #include "joypad.h"
- #include "mem.h"
- #include "regs.h"
-
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <exec/memory.h>
-
- #include <powerup/ppcproto/intuition.h>
- #include <powerup/ppclib/interface.h>
- #include <powerup/ppclib/time.h>
- #include <powerup/gcclib/powerup_protos.h>
- #include <powerup/ppcproto/exec.h>
- #include <powerup/ppcinline/graphics.h>
- #include <powerup/ppcproto/dos.h>
- #include <powerup/ppcproto/lowlevel.h>
- #include <powerup/ppcproto/asl.h>
-
- #include <cybergraphx/cybergraphics.h>
- #include <powerup/ppcinline/cybergraphics.h>
-
- #define AGA 0
- #define CGFX 1
-
- /* Misc variables */
- ULONG rgbtab[1+3*256+1];
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
- struct Library *AslBase;
- struct Library *CyberGfxBase;
- struct Library *LowLevelBase;
- struct Screen *screen=NULL;
- struct Window *window=NULL;
- UWORD *EmptyPointer;
- struct ScreenModeRequester *screenreq;
- struct BitMap agabitmap;
-
- /* CGFX variables */
- unsigned long pixfmt;
- unsigned char *baseaddress;
- int bpr;
-
- int xoffset, yoffset;
- int width = 320, height = 256, screentype;
- unsigned char *agabuf;
-
- int use_pad = 0;
- int use_cgfx = 0;
- int use_req = 0;
- int use_highcolor = 0;
-
- static unsigned long
- gbe_window_width = 0,
- gbe_window_height = 0;
-
- static char *gfx_buffer = (char *)NULL;
- static short *gfx_buffer_high = (char *)NULL;
-
- #define twomerges1(a, b, c, d, shift, mask) \
- { \
- temp1 = b; \
- temp2 = d; \
- temp1 >>= shift; \
- temp2 >>= shift; \
- temp1 ^= a; \
- temp2 ^= c; \
- temp1 &= mask; \
- temp2 &= mask; \
- a ^= temp1; \
- c ^= temp2; \
- temp1 <<= shift; \
- temp2 <<= shift; \
- b ^= temp1; \
- d ^= temp2; \
- }
-
- void c2p(void *chunky, void *bitplanes, int chunkyx, int chunkyy, int xoffset, int yoffset, int bitplanesize)
- {
- ULONG *c;
- ULONG temp1, temp2;
- ULONG *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7;
- ULONG d0, d1, d2, d3, d4, d5, d6, d7;
- ULONG t0, t1, t2, t3, t4, t5, t6, t7;
- ULONG xadd, addx;
- int i,j=0;
-
- c = (ULONG *) chunky;
- p0 = (ULONG *) (&(((char *) bitplanes)[(yoffset*chunkyx + yoffset*xoffset*2 + xoffset) >> 3]));
- p1 = (ULONG *) (&(((char *) p0)[bitplanesize]));
- p2 = (ULONG *) (&(((char *) p1)[bitplanesize]));
- p3 = (ULONG *) (&(((char *) p2)[bitplanesize]));
- p4 = (ULONG *) (&(((char *) p3)[bitplanesize]));
- p5 = (ULONG *) (&(((char *) p4)[bitplanesize]));
- p6 = (ULONG *) (&(((char *) p5)[bitplanesize]));
- p7 = (ULONG *) (&(((char *) p6)[bitplanesize]));
-
- addx=chunkyx / (sizeof (ULONG) *8);
- xadd=xoffset * 2 / (sizeof (ULONG) * 8);
- i = chunkyx * chunkyy / (sizeof (ULONG) * 8);
-
- d0 = *c++;
- d1 = *c++;
- d2 = *c++;
- d3 = *c++;
- d4 = *c++;
- d5 = *c++;
- d6 = *c++;
- d7 = *c++;
-
- twomerges1(d0, d4, d1, d5, 16, 0x0000ffff);
- twomerges1(d2, d6, d3, d7, 16, 0x0000ffff);
-
- twomerges1(d0, d2, d1, d3, 8, 0x00ff00ff);
- twomerges1(d4, d6, d5, d7, 8, 0x00ff00ff);
-
- twomerges1(d0, d1, d2, d3, 4, 0x0f0f0f0f);
- twomerges1(d4, d5, d6, d7, 4, 0x0f0f0f0f);
-
- twomerges1(d0, d4, d1, d5, 2, 0x33333333);
- twomerges1(d2, d6, d3, d7, 2, 0x33333333);
-
- twomerges1(d0, d2, d1, d3, 1, 0x55555555);
- twomerges1(d4, d6, d5, d7, 1, 0x55555555);
-
- t0 = d7;
- t1 = d5;
- t2 = d3;
- t3 = d1;
- t4 = d6;
- t5 = d4;
- t6 = d2;
- t7 = d0;
-
- while (--i)
- {
- d0 = *c++;
- d1 = *c++;
- d2 = *c++;
- d3 = *c++;
- d4 = *c++;
- d5 = *c++;
- d6 = *c++;
- d7 = *c++;
-
- *p0++ = t0;
-
- twomerges1(d0, d4, d1, d5, 16, 0x0000ffff);
- twomerges1(d2, d6, d3, d7, 16, 0x0000ffff);
-
- *p1++ = t1;
-
- twomerges1(d0, d2, d1, d3, 8, 0x00ff00ff);
- twomerges1(d4, d6, d5, d7, 8, 0x00ff00ff);
-
- *p2++ = t2;
-
- twomerges1(d0, d1, d2, d3, 4, 0x0f0f0f0f);
- twomerges1(d4, d5, d6, d7, 4, 0x0f0f0f0f);
-
- *p3++ = t3;
-
- twomerges1(d0, d4, d1, d5, 2, 0x33333333);
- twomerges1(d2, d6, d3, d7, 2, 0x33333333);
-
- *p4++ = t4;
-
- twomerges1(d0, d2, d1, d3, 1, 0x55555555);
- twomerges1(d4, d6, d5, d7, 1, 0x55555555);
-
- *p5++ = t5;
- *p6++ = t6;
- *p7++ = t7;
-
- t0 = d7;
- t1 = d5;
- t2 = d3;
- t3 = d1;
- t4 = d6;
- t5 = d4;
- t6 = d2;
- t7 = d0;
-
- j++;
-
- if (j==addx)
- {
- p0+=xadd;
- p1+=xadd;
- p2+=xadd;
- p3+=xadd;
- p4+=xadd;
- p5+=xadd;
- p6+=xadd;
- p7+=xadd;
- j=0;
- }
- }
-
- *p0++ = t0;
- *p1++ = t1;
- *p2++ = t2;
- *p3++ = t3;
- *p4++ = t4;
- *p5++ = t5;
- *p6++ = t6;
- *p7++ = t7;
- }
-
- int open_libraries()
- {
- IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 39);
- if (IntuitionBase==NULL)
- return -1;
-
- GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 39);
- if (GfxBase==NULL)
- {
- CloseLibrary(IntuitionBase);
- return -1;
- }
-
- AslBase = OpenLibrary("asl.library", 39);
- if (AslBase==NULL)
- {
- CloseLibrary(GfxBase);
- CloseLibrary(IntuitionBase);
- return -1;
- }
-
- CyberGfxBase = OpenLibrary("cybergraphics.library", 40);
- LowLevelBase = OpenLibrary("lowlevel.library", 39);
-
- return 0;
- }
-
- void close_libraries()
- {
- if (LowLevelBase != NULL)
- CloseLibrary(LowLevelBase);
- if (CyberGfxBase != NULL)
- CloseLibrary(CyberGfxBase);
- CloseLibrary(AslBase);
- CloseLibrary(GfxBase);
- CloseLibrary(IntuitionBase);
- }
-
- void close_screen()
- {
- CloseWindow(window);
- CloseScreen(screen);
- }
-
- int open_screen()
- {
- unsigned long dispid;
- unsigned char *temp;
- int i, depth = 8;
-
- if (use_req == 1)
- {
- screenreq = AllocAslRequestTags(ASL_ScreenModeRequest, TAG_END);
-
- if (AslRequest(screenreq, TAG_END))
- {
- dispid=screenreq->sm_DisplayID;
- width=screenreq->sm_DisplayWidth;
- FreeAslRequest(screenreq);
- }
- else
- {
- FreeAslRequest(screenreq);
- return -1;
- }
-
- if (width != 320)
- {
- printf("You must choose a width of 320 pixels\n");
- return -1;
- }
-
- screentype = AGA;
-
- if (CyberGfxBase != NULL)
- {
- if (IsCyberModeID(dispid))
- {
- depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, dispid);
-
- if ((depth != 8) && (depth != 15))
- {
- printf("You must choose a 8bit or 15bit screenmode\n");
- return -1;
- }
- else
- screentype = CGFX;
- }
- }
- }
- else
- {
- if (CyberGfxBase != NULL)
- {
- if (use_highcolor == 1)
- {
- depth = 15;
- if ((dispid=BestCModeIDTags(CYBRBIDTG_NominalWidth, width,
- CYBRBIDTG_NominalHeight, height,
- CYBRBIDTG_Depth, depth,
- TAG_DONE))==INVALID_ID)
- {
- printf("Could NOT get best mode ID!\n");
- return -1;
- }
- }
- else
- {
- depth = 8;
- if ((dispid=BestCModeIDTags(CYBRBIDTG_NominalWidth, width,
- CYBRBIDTG_NominalHeight, height,
- CYBRBIDTG_Depth, depth,
- TAG_DONE))==INVALID_ID)
- {
- printf("Could NOT get best mode ID!\n");
- return -1;
- }
- }
- screentype = CGFX;
- }
- else
- {
- dispid = 0x00021000; /* PAL Lores */
- screentype = AGA;
- }
- }
-
- if (screentype == AGA)
- {
- /* Allocate resources */
- temp = (unsigned char*)AllocRaster(width, height*8);
- memset(temp, 0, width*height);
-
- InitBitMap(&agabitmap, 8, width, height);
-
- for(i=0; i<8; i++)
- agabitmap.Planes[i] = temp + i * RASSIZE(width, height);
-
- /* Open screen */
- screen = OpenScreenTags(NULL,
- SA_BitMap,(int)&agabitmap,
- SA_Width,width,
- SA_Height,height,
- SA_Depth,8,
- SA_Quiet,TRUE,
- SA_ShowTitle,FALSE,
- SA_Type,CUSTOMSCREEN,
- SA_DisplayID,dispid,
- TAG_DONE);
-
- /* Could the screen be opened? */
- if(screen == NULL)
- {
- printf("The screen could NOT be opened!\n");
- return -1;
- }
- }
- else
- {
- /* Open screen */
- screen = OpenScreenTags(NULL,
- SA_Width,width,
- SA_Height,height,
- SA_Depth,8,
- SA_Quiet,TRUE,
- SA_ShowTitle,FALSE,
- SA_Type,CUSTOMSCREEN,
- SA_DisplayID,dispid,
- TAG_DONE);
-
- /* Could the screen be opened? */
- if(screen == NULL)
- {
- printf("The screen could NOT be opened!\n");
- return -1;
- }
-
- /* Get CGFX screenmode information */
- UnLockBitMap(LockBitMapTags(screen->RastPort.BitMap,
- LBMI_PIXFMT, (ULONG)&pixfmt,
- LBMI_BASEADDRESS, (ULONG)&baseaddress,
- LBMI_BYTESPERROW, (ULONG)&bpr,
- TAG_END));
- }
-
- /* Open window */
- window=OpenWindowTags(NULL,
- WA_CustomScreen,(int)screen,
- WA_Width,width,
- WA_Height,height,
- WA_IDCMP,IDCMP_RAWKEY,
- WA_Backdrop,TRUE,
- WA_Borderless,TRUE,
- WA_Activate,TRUE,
- TAG_DONE);
-
- /* Could the window be opened? */
- if(window == NULL)
- {
- CloseScreen(screen);
- printf("The window could NOT be opened!\n");
- return -1;
- }
-
- if (depth == 8)
- {
- use_highcolor = 0;
-
- /* Set a 3:3:2 palette */
- for(i=0; i<256; i++)
- {
- rgbtab[1+i*3+0]=((i & 0xe0))<<24;
- rgbtab[1+i*3+1]=((i & 0x1c) << 3)<<24;
- rgbtab[1+i*3+2]=((i & 0x03) << 6)<<24;
- }
-
- rgbtab[0]=(256<<16)|0;
- rgbtab[1+256*3]=0;
- LoadRGB32(&screen->ViewPort, rgbtab);
- }
- else
- {
- use_highcolor = 1;
- FillPixelArray(&screen->RastPort, 0, 0, width, height, 0L);
- }
-
- /* Hide the pointer */
- EmptyPointer = AllocVec(512, MEMF_CHIP|MEMF_CLEAR);
- SetPointer(window, EmptyPointer, 1, 1, 0, 0);
-
- /* Force CD32 pad (if required) */
- if ((LowLevelBase != NULL) && (use_pad == 1))
- SetJoyPortAttrs(1, SJA_Type, SJA_TYPE_GAMECTLR, TAG_END);
-
- if (screentype == AGA)
- {
- agabuf = (unsigned char *)malloc(width*height);
- memset(agabuf, 0, width*height);
- }
-
- return 0;
- }
-
- int gbe_init_amiga(char *display)
- {
- if (open_libraries() < 0)
- {
- return 0;
- }
- else
- {
- if (open_screen() < 0)
- {
- close_libraries();
- return 0;
- }
- }
-
- if (use_highcolor == 1)
- return 2;
- else
- return 1;
- }
-
- int gbe_close_amiga()
- {
- close_screen();
- if (screentype == AGA)
- {
- free(agabuf);
- FreeRaster(agabitmap.Planes[0], width, height*8);
- }
- close_libraries();
-
- return 1;
- }
-
- int gbe_create_window_amiga(char *title, int width, int height)
- {
- gbe_window_width = width;
- gbe_window_height = height;
- xoffset = (320-width)/2;
- yoffset = (256-height)/2;
-
- if (use_highcolor == 1)
- {
- gbe_window_width *= 2;
- xoffset *= 2;
- }
-
- /* AmigaOS is all good, allocate buffer */
- gfx_buffer = (char *)malloc(width * height * 2);
- if(!gfx_buffer) {
- printf("unable to alloc buffer!\n");
- return 0;
- }
-
- gfx_buffer_high = (short *)gfx_buffer;
-
- return 1;
- }
-
- int gbe_poll_events_amiga()
- {
- ULONG imCode, imClass, portstate;
- struct IntuiMessage *imsg = NULL;
-
- if ((use_pad == 0) || (LowLevelBase == NULL))
- {
-
- /* Check for IDCMP messages */
- if ((imsg=(struct IntuiMessage *)GetMsg(window->UserPort)))
- {
- imClass=imsg->Class;
- imCode=imsg->Code;
-
- ReplyMsg((struct Message *)imsg);
-
- /* KeyPress and KeyReleases */
- if(imClass==IDCMP_RAWKEY)
- {
- if(imCode<128) /* Key is being pressed */
- {
- switch(imCode)
- {
- case 69: /* ESC */
- joypad_press(GBE_O_ESCAPE);
- break;
-
- case 16: /* Q */
- joypad_press(GBE_START);
- break;
-
- case 17: /* W */
- joypad_press(GBE_SELECT);
- break;
-
- case 32: /* A */
- joypad_press(GBE_A);
- break;
-
- case 33: /* S */
- joypad_press(GBE_B);
- break;
-
- case 78: /* RIGHT */
- joypad_press(GBE_RIGHT);
- break;
-
- case 79: /* LEFT */
- joypad_press(GBE_LEFT);
- break;
-
- case 77: /* DOWN */
- joypad_press(GBE_DOWN);
- break;
-
- case 76: /* UP */
- joypad_press(GBE_UP);
- break;
-
- default:
- break;
- } /* switch(imCode) */
- }
- else /* (imCode>127), Key released */
- {
- imCode-=128; /* Remove "Key released" bit */
- switch(imCode)
- {
- case 69: /* ESC */
- joypad_release(GBE_O_ESCAPE);
- break;
-
- case 16: /* Q */
- joypad_release(GBE_START);
- break;
-
- case 17: /* W */
- joypad_release(GBE_SELECT);
- break;
-
- case 32: /* A */
- joypad_release(GBE_A);
- break;
-
- case 33: /* S */
- joypad_release(GBE_B);
- break;
-
- case 78: /* RIGHT */
- joypad_release(GBE_RIGHT);
- break;
-
- case 79: /* LEFT */
- joypad_release(GBE_LEFT);
- break;
-
- case 77: /* DOWN */
- joypad_release(GBE_DOWN);
- break;
-
- case 76: /* UP */
- joypad_release(GBE_UP);
- break;
-
- default:
- break;
- } /* switch(imCode) */
- } /* (imCode>127), Key released */
- } /* imClass=IDCMP_RAWKEY */
- } /* Check for IDCMP messages */
-
- }
- else
- {
-
- /* Check for IDCMP messages */
- if ((imsg=(struct IntuiMessage *)GetMsg(window->UserPort)))
- {
- imClass=imsg->Class;
- imCode=imsg->Code;
-
- ReplyMsg((struct Message *)imsg);
-
- /* KeyPress and KeyReleases */
- if(imClass==IDCMP_RAWKEY)
- {
- if(imCode<128) /* Key is being pressed */
- {
- switch(imCode)
- {
- case 69: /* ESC */
- joypad_press(GBE_O_ESCAPE);
- break;
-
- default:
- break;
- } /* switch(imCode) */
- }
- else /* (imCode>127), Key released */
- {
- imCode-=128; /* Remove "Key released" bit */
- switch(imCode)
- {
- case 69: /* ESC */
- joypad_release(GBE_O_ESCAPE);
- break;
-
- default:
- break;
- } /* switch(imCode) */
- } /* (imCode>127), Key released */
- } /* imClass=IDCMP_RAWKEY */
- } /* Check for IDCMP messages */
-
- /* Read port 1 (joyport) */
- portstate = ReadJoyPort(1);
-
- if (portstate&JPF_JOY_RIGHT) /* RIGHT */
- joypad_press(GBE_RIGHT);
- else
- joypad_release(GBE_RIGHT);
-
- if (portstate&JPF_JOY_LEFT) /* LEFT */
- joypad_press(GBE_LEFT);
- else
- joypad_release(GBE_LEFT);
-
- if (portstate&JPF_JOY_DOWN) /* DOWN */
- joypad_press(GBE_DOWN);
- else
- joypad_release(GBE_DOWN);
-
- if (portstate&JPF_JOY_UP) /* UP */
- joypad_press(GBE_UP);
- else
- joypad_release(GBE_UP);
-
- if (portstate&JPF_BUTTON_GREEN) /* Q */
- joypad_press(GBE_START);
- else
- joypad_release(GBE_START);
-
- if (portstate&JPF_BUTTON_YELLOW) /* W */
- joypad_press(GBE_SELECT);
- else
- joypad_release(GBE_SELECT);
-
- if (portstate&JPF_BUTTON_RED) /* A */
- joypad_press(GBE_A);
- else
- joypad_release(GBE_A);
-
- if (portstate&JPF_BUTTON_BLUE) /* S */
- joypad_press(GBE_B);
- else
- joypad_release(GBE_B);
-
- }
-
- return 1;
- }
-
- int gbe_blit_amiga()
- {
- unsigned char *src, *dst;
- int i;
-
- if (screen != NULL)
- {
- if (screentype == AGA)
- {
- c2p((void *)gfx_buffer, (void *)agabitmap.Planes[0], gbe_window_width, gbe_window_height, xoffset, yoffset, RASSIZE(width, height));
- }
- else
- {
- if ((use_cgfx == 1) && (use_highcolor == 0))
- {
- WritePixelArray(gfx_buffer, 0, 0, gbe_window_width, &screen->RastPort, xoffset, yoffset, gbe_window_width, gbe_window_height, RECTFMT_LUT8);
- }
- else
- {
- /* Init pointers */
- dst = baseaddress+(yoffset*bpr)+(xoffset);
- src = gfx_buffer;
-
- /* Perform copy */
- for (i=0; i<gbe_window_height; i++)
- {
- memcpy(dst, src, gbe_window_width);
- dst += bpr;
- src += gbe_window_width;
- }
- }
- }
- }
-
- return 1;
- }
-
- int gbe_plot_amiga(int x, int y, int color)
- {
- if (use_highcolor)
- gfx_buffer_high[(y * (gbe_window_width >> 1)) + (x)] = color & 0xFFFF;
- else
- gfx_buffer[(y * (gbe_window_width)) + (x)] = color & 0xFF;
-
- return 1;
- }
-
- #else
-
- int gbe_init_amiga(char *display)
- {
- return 0;
- }
-
- int gbe_close_amiga()
- {
- return 1;
- }
-
- int gbe_create_window_amiga(char *title, int width, int height)
- {
- return 1;
- }
-
-
- int gbe_poll_events_amiga()
- {
- return 1;
- }
-
- int gbe_blit_amiga()
- {
- return 1;
- }
-
- int gbe_plot_amiga(int x, int y, int color)
- {
- return 1;
- }
-
- #endif
-