/* * Commodore 64 Spoof Emulator (C) Eddy Carroll, 1st April 1988 * * Module: SCREEN.C * * This module contains the various screen handling routines used by * the emulator. * */ #define SCREEN #include #include #include #include #include #include #include "screen.h" struct RastPort *rp; int openconsole = 0; struct NewScreen NewScreen = { 0,0,320,200, /* Screen position & size */ 2, /* 2 bitplanes = 4 colours */ 0,1, /* Default text colours */ 0, /* Lores, non-interlace */ CUSTOMSCREEN, /* Screen type */ 0, /* Use default font for now */ "C64 Emulator", /* Screen title */ 0, /* No gadgets */ 0 /* No custom bitmap */ }; #define NORMALFLAGS WINDOWCLOSE | WINDOWSIZING | WINDOWDEPTH | WINDOWDRAG struct NewWindow NewWindow = { 0,0,320,200, /* Window position & Size */ 0,1, /* Default text colours */ MENUPICK | /* Ok, we want to know */ INTUITICKS, /* about menus & timings */ BACKDROP | /* These four flags define */ BORDERLESS | /* the type of window we */ ACTIVATE | /* open. Here, we want an */ 0 , /* "invisible" window. */ NULL, /* No gadgets */ NULL, /* Default menus check mark */ NULL, /* No window title */ NULL, /* Will point to our screen */ NULL, /* No special bitmap used */ 0,0,320,200, /* No resizing so not used */ CUSTOMSCREEN /* Open this on OUR screen */ }; UWORD blackcol[4] = { /* All black array for initial screen */ 0,0,0,0}; UWORD screencol[4] = { /* Default colours for custom screen */ 0x077E, /* Colour 0 = Light blue */ 0x0EEE, /* Colour 1 = White */ 0x077E, /* Colour 2 = Lighter blue */ 0x011C /* Colour 3 = Dark Blue */ }; struct IntuiText mytext[] = { /* Pens Mode Pos Font Text Next */ { 0,1, JAM1, 0,0, NULL, (UBYTE *)" About...", NULL}, { 0,1, JAM1, 0,0, NULL, (UBYTE *)" Show Title", NULL}, { 0,1, JAM1, 0,0, NULL, (UBYTE *)" Quit", NULL}}; #define MENUFLAGS ITEMTEXT | ITEMENABLED | HIGHCOMP #define IDATA(off,str,key) 0,off,110,9,MENUFLAGS,0,str,NULL,key,NULL,NULL struct MenuItem myitems[] = { { &myitems[1], IDATA( 0, (APTR)&mytext[0], M_ABOUT) }, { &myitems[2], IDATA(10, (APTR)&mytext[1], M_TITLE) }, { NULL, IDATA(20, (APTR)&mytext[2], M_QUIT ) }}; struct Menu mymenus = {NULL, 0,0,100,10, MENUENABLED, "Project", myitems}; /* * Free all resources allocated in this module * */ void cleanup(err) int err; { if (openconsole) CloseDevice(ConReadReq); if (ConReadReq) DeleteStdIO(ConReadReq); if (ConReadPort) DeletePort(ConReadPort); if (mywin) { ClearMenuStrip(mywin); CloseWindow(mywin); } if (myscreen) CloseScreen(myscreen); if (IntuitionBase) CloseLibrary(IntuitionBase); if (GfxBase) CloseLibrary(GfxBase); exit(err); } /* * Clears the screen * */ void clearscreen() { register char *p; register int i; SetRast(rp,3); for (p = (char *)screen, i = 1000; i--; *p++ = ' ') ; cursorx = 0; cursory = 0; } /* * Tells console device we want to read a character from keyboard * */ void QueueRead(request,whereto) struct IOStdReq *request; char *whereto; { request->io_Command = CMD_READ; request->io_Data = (APTR)whereto; request->io_Length = 1; SendIO(request); } /* * Initialises the screen, character set, colours etc. Exits program with * error code if an error occurs. * */ void initscreen() { if (!mywin) { if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)) == 0) cleanup(1); if ((GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)) == 0) cleanup(2); if ((myscreen = (struct Screen *)OpenScreen(&NewScreen)) == 0) cleanup(3); LoadRGB4(&(myscreen->ViewPort),blackcol,4); ShowTitle(myscreen,0); NewWindow.Screen = myscreen; if ((mywin = (struct Window *)OpenWindow(&NewWindow)) == 0) cleanup(4); SetMenuStrip(mywin, &mymenus); rp = mywin->RPort; /* Initialise communication ports for Console */ if ((ConReadPort = CreatePort(0,0)) == NULL) cleanup(5); if ((ConReadReq = CreateStdIO(ConReadPort)) == NULL) cleanup(6); ConReadReq->io_Data = (APTR)mywin; ConReadReq->io_Length = sizeof(*mywin); /* Open console and tell it to turn off the cursor */ if (OpenDevice("console.device",0,ConReadReq,0)) cleanup(7); openconsole = 1; /* Tell console to get first character ready for us */ QueueRead(ConReadReq,constring); SetAPen(rp,2); /* Set primary colour */ SetBPen(rp,3); /* Set secondary colour */ clearscreen(); /* Fill screen to raster colour */ LoadRGB4(&(myscreen->ViewPort),screencol,4); } } /* * Outputs a character to the screen at co-ordinates x,y. If mode is 0, * then output normal character, else output reverse character. * */ void writechar(x,y,ch,mode) int x,y; char ch; int mode; { char s[2]; s[0] = ch; Move(rp,x * 8, y * 8 + 6); /* Quick multiply by 8 */ if (mode) { SetDrMd(rp,INVERSVID|JAM2); Text(rp,s,1); SetDrMd(rp, JAM2); } else Text(rp,s,1); } /* * Scrolls the screen up one line. Both the visible rastport screen, * and the internal screen are scrolled. * */ void scrollup() { register char *p, *q; register int i; ScrollRaster(rp,0,8,0,0,319,199); for (p = (char *)screen,q = (char *)screen+40, i = 960; i--; *p++ = *q++) ; for (i = 40; i--; *p++ = ' ') ; cursory--; } /* * Handles special characters like CR, cursor keys etc. * */ void special(ch) char ch; { register char *p, *q; register int i,j; switch (ch) { case C_CR: /* Carriage Return */ cursorx = 0; cursory++; if (cursory >= 25) scrollup(); break; case C_UP: /* Cursor Up */ if (cursory) cursory--; break; case C_DOWN: /* Cursor Down */ cursory++; if (cursory >= 25) scrollup(); break; case C_LEFT: /* Cursor Left */ if (cursorx == 0) { if (cursory) { cursorx = 39; cursory--; } } else cursorx--; break; case C_RIGHT: /* Cursor Right */ cursorx++; if (cursorx >= 40) { cursorx = 0; cursory++; if (cursory >= 25) scrollup(); } break; case C_DEL: /* Delete */ if (cursorx == 0) { if (cursory) { cursorx = 39; cursory--; screen[cursory][cursorx] = ' '; writechar(cursorx,cursory,' ',0); } } else { ScrollRaster(rp,8,0,cursorx*8,cursory*8,319,cursory*8+7); /* Move chars from here to end of line back one space */ for (q = &(screen[cursory][cursorx]), p = q - 1, i = 40 - cursorx; i--; *p++ = *q++) ; *p = ' '; cursorx--; } break; case C_INSERT: /* Insert */ if (screen[cursory][39] == ' ' && cursorx < 39) { ScrollRaster(rp,-8,0,cursorx*8,cursory*8,319,cursory*8+7); for (p = &screen[cursory][39], q = p - 1, i = 39 - cursorx; i--; *p-- = *q--) ; *p = ' '; } break; case C_CLEAR: /* Clear screen */ clearscreen(); break; case C_HOME: /* Home cursor */ cursorx = 0; cursory = 0; break; case C_REDRAW: /* Redraw entire screen */ for (i = 0; i < 25; i++) for (j = 0; j < 40; j++) writechar(j,i,screen[i][j],0); break; } } /* * Outputs character to screen at current cursor position, and advances * cursor to next position. Scrolls screen if necessary. * */ void printchar(ch) char ch; { if (ch < ' ') special(ch); else { writechar(cursorx,cursory,ch,0); screen[cursory][cursorx] = ch; cursorx++; if (cursorx >= 40) { cursorx = 0; cursory++; if (cursory >= 25) scrollup(); } } } /* * Outputs string to screen at current cursor position * */ void printmess(s) char *s; { while (*s) printchar(*s++); }