From 8cd92634533100a29f216f0a53ccb42321de342e Mon Sep 17 00:00:00 2001 From: ArthurFerreira2 Date: Fri, 14 Aug 2020 21:42:31 +0200 Subject: [PATCH] Function keys updated --- README.md | 51 ++++++++++----------- reinetteII+.c | 124 +++++++++++++++++++++++--------------------------- 2 files changed, 80 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index a443c30..9f95d54 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ ![screenshots](screenshots.png) -After [reinette](https://github.com/ArthurFerreira2/reinette) (Apple 1 emulator) and [reinette II](https://github.com/ArthurFerreira2/reinette-II) (the text only Apple II emulator), I am proud to release **reinette II plus**, a french\* Apple II plus emulator using SDL2. +After [reinette](https://github.com/ArthurFerreira2/reinette) (Apple 1 emulator) and [reinette II](https://github.com/ArthurFerreira2/reinette-II) (the text only Apple II emulator), I am proud to release **reinette II plus**, a French\* Apple II plus emulator using SDL2. -\* reinette has two meanings in french : it's a little frog but also a delicious kind of apple +\* reinette has two meanings in French : it's a little frog but also a delicious kind of apple [download windows binaries](https://github.com/ArthurFerreira2/reinette-II-plus/releases/tag/0.2b) @@ -26,7 +26,6 @@ After [reinette](https://github.com/ArthurFerreira2/reinette) (Apple 1 emulator) It uses the same MOS 6502 CPU emulator as her sisters (now christened [puce6502](https://github.com/ArthurFerreira2/puce6502)).\ You only need SDL2 to compile it. (I'm not using SDL_Mixer, but only the native SDL2 audio functions) - This emulator is not accurate in many ways and does not compete with [AppleWin](https://github.com/AppleWin/AppleWin), [Epple](https://github.com/cmosher01/Epple-II) or [LinApple](https://github.com/linappleii/linapple). Better use one of them if you want a good Apple ][ emulation experience. @@ -36,70 +35,68 @@ It's compact, less than 1000 SLOC, with two source files only, one for the CPU e I did my best to comment the code, and if you have an idea of how an Apple ][ works, it should be easy for you to understand the code, modify and enhance it for your needs (see TODO section). - ### Startup - You can specify a .nib file on the command line to start the emulator with a floppy engaged in drive 1. Otherwise, the emulator will start with no floppy (and thus wait one until you press the reset key or drag and drop a .nib file) - + You can specify a .nib file on the command line to start the emulator with a floppy engaged in drive 1. Otherwise, the emulator will start with no floppy (and thus waits until you press the reset key or drag and drop a .nib file) ### Usage Drag and drop a disk image file (.nib format only) to insert it into drive 1\ -Drop the file while pressing the ALT key to insert it into drive 2 +**reinette II plus** will reboot immediately and try to boot the floppy.\ +Press CTRL while dropping the file if you don't want the emulator to reboot \ +Pressing the ALT key while dropping the file inserts it into drive 2. -Use the functions keys to control the emulator itself +Use the functions keys to control the emulator itself : ``` * F1 : writes the changes of the floppy in drive 0 back to host * F2 : writes the changes of the floppy in drive 1 back to host -* F3 : pause / un-pause the emulator -* F4 : paste text from clipboard -* F5 : zoom out down to 1:1 pixels -* F6 : zoom in, no magnification limit -* F7/F8 : adjust joystick trim -* F9 : mute / un-mute sound -* F10 : monochrome / color display (only in HGR mode) -* F11 : reset -* CTRL-F11 : break +* F3 : zoom out down to 1:1 pixels +* F4 : zoom in, no magnification limit +* F5 : reduce joystick trim +* F6 : increase joystick trim +* F7 : paste text from clipboard +* F8 : mute / un-mute sound +* F9 : monochrome / color display (only in HGR mode) +* F10 : pause / un-pause the emulator +* F11 : reset / CTRL-F11 : break * F12 : quit the emulator -Paddles / Joystic : +Paddles / Joystick : * numpad 1 : left * numpad 3 : right +* numpad 5 : up * numpad 2 : down -* numpad 3 : up * CTRL : button 0 * ALT : button 1 +* SHIFT : button 2 (allow applications to use the shift mod) ``` ### Limitations -* high pitch noise at high volume on windows (Linux Ubuntu tested OK) +* ~~high pitch noise at high volume on windows (Linux Ubuntu tested OK)~~ * sound cracks when playing for long period (intro music for example) * CPU is not 100% cycle accurate - see source file for more details * colors are approximate (taken from a scan of an old Beagle bros. poster) * ~~HGR video is inaccurate, and does not implement color fringing~~ -* disk ][ access is artificially accelerated +* disk ][ access is artificially accelerated - considered as a feature * only support .nib floppy images. (you can use [CiderPress](https://github.com/fadden/ciderpress) to convert your images to this format) * only has 48KB of RAM (can't run software requiring the language card) * and many others ... - ### To do +* fix sound cracks * give a warning if the application exits with unsaved floppy changes -* give the user the option to start with the original Apple II rom -* colors where taken from an old Beagle Bros poster, find more accurate RGB values. +* check for more accurate RGB values. * ~~implement color fringe effect in HGR~~ -* optimize sound generation -* optimize disk access (speed is actually a bit artificial) * re-implement Paddles and Joystick support for analog simulation * implement the language card and extend the RAM of **reinette II plus** to 64K to support more software. * for 6502 coders : * add the ability to insert a binary file at a specified address + * give the user the option to start with the original Apple II rom * dump regs, soft switches and specified memory pages to console -Follow me to be updated ! \ \ \ diff --git a/reinetteII+.c b/reinetteII+.c index 530ae65..741222c 100644 --- a/reinetteII+.c +++ b/reinetteII+.c @@ -30,7 +30,6 @@ #include "puce6502.h" - //================================================================ SOFT SWITCHES uint8_t KBD = 0; // 0xC000, 0xC010 ascii value of keyboard input @@ -54,12 +53,13 @@ float trimGC = .24; double rate = 23.19727891156463; // 1023000 Hz / 44100 Hz (the wavSpec.freq) bool muted = false; // press F9 to mute/unmute SDL_AudioDeviceID audioDevice; -Sint8 audioBuffer[2][audioBufferSize] = {0}; // see main() for more details +Sint8 audioBuffer[2][audioBufferSize] = {0}; // see main() for more details //====================================================================== DISK ][ uint8_t slot6[256] = {0}; // P5A disk ][ PROM in slot 6 +int curDrv = 0; // only one can be enabled at a time struct drive{ char filename[512]; // the full disk image path @@ -71,8 +71,6 @@ struct drive{ uint16_t nibble; // ptr to nibble under head position } disk[2] = {0}; // two disk ][ drive units -int curDrv = 0; // only one can be enabled at a time - int insertFloppy(SDL_Window *wdo, char *filename, int drv){ int i, a, b; @@ -113,6 +111,19 @@ int insertFloppy(SDL_Window *wdo, char *filename, int drv){ return(1); } +int saveFloppy(int drive){ + if (disk[drive].filename[0] && !disk[drive].readOnly){ + FILE *f = fopen(disk[drive].filename, "wb"); + if (f){ + if (fwrite(disk[drive].data, 1, 232960, f) != 232960){ + printf("Write failed\n"); + return(0); + } + fclose(f); + } + } + return(1); +} void stepMotor(uint16_t address){ static bool phases[2][4] = {0}; // phases states (for both drives) @@ -244,7 +255,7 @@ int main(int argc, char *argv[]){ int zoom = 2; const float frameDelay = 1000/60; // targeting 60 FPS float fps = 60; - Uint32 frameStart = 0, frameTime = 0, frame = 0, reftime = 0, blink = 0; + Uint32 frameStart = 0, frameTime = 0, frame = 0, reftime = 0; SDL_Event event; bool paused = false, running = true, ctrl, shift, alt; @@ -258,9 +269,9 @@ int main(int argc, char *argv[]){ SDL_Window *wdo = SDL_CreateWindow("reinette II+", SDL_WINDOWPOS_CENTERED, \ SDL_WINDOWPOS_CENTERED, 280*zoom, 192*zoom, SDL_WINDOW_OPENGL); - SDL_Surface *icon = SDL_LoadBMP("icon.bmp"); // add an icon to the window title bar - SDL_SetColorKey(icon, SDL_TRUE, SDL_MapRGB(icon->format, 255, 255, 255)); - SDL_SetWindowIcon(wdo, icon); + SDL_Surface *icon = SDL_LoadBMP("icon.bmp"); // add an icon to the window title bar + SDL_SetColorKey(icon, SDL_TRUE, SDL_MapRGB(icon->format, 255, 255, 255)); + SDL_SetWindowIcon(wdo, icon); SDL_Renderer *rdr = SDL_CreateRenderer(wdo, -1, SDL_RENDERER_ACCELERATED); // | SDL_RENDERER_PRESENTVSYNC); SDL_SetRenderDrawBlendMode(rdr, SDL_BLENDMODE_NONE); // SDL_BLENDMODE_BLEND); @@ -294,12 +305,13 @@ int main(int argc, char *argv[]){ uint16_t previousDots[192][40] = {0}; // check which Hi-Res 7 dots needs redraw int previousBit[192][40] = {0}; // the last bit value of the byte before. - uint8_t glyph; // a TEXT character, or 2 blocks in GR - uint8_t colorIdx = 0; // to index the color arrays - uint16_t vRamBase = 0x0400; // can be 0x0400, 0x0800, 0x2000 or 0x4000 int lineLimit; - enum characterAttribute {A_NORMAL, A_INVERSE, A_FLASH} glyphAttribute; + uint8_t glyph; // a TEXT character, or 2 blocks in GR + bool blink = true; // cursor blinking + uint8_t colorIdx = 0; // to index the color arrays bool monochrome = false; + uint16_t vRamBase = 0x0400; // can be 0x0400, 0x0800, 0x2000 or 0x4000 + enum characterAttribute {A_NORMAL, A_INVERSE, A_FLASH} glyphAttribute; SDL_Rect drvRect[2] = { {272, 188, 4, 4}, {276, 188, 4, 4} }; // disk drive status squares SDL_Rect pixelGR = {0, 0, 7, 4}; // a block in LoRes @@ -318,7 +330,7 @@ int main(int argc, char *argv[]){ {151, 88, 34}, {234, 108, 21}, {158, 151,143}, {255, 206, 240}, {144, 192, 49}, {255, 253, 166}, {159, 210,213}, {255, 255, 255}}; - const int hcolor[16][3] = { // the high res colors (2 lights) + const int hcolor[16][3] = { // the high res colors (2 light levels) { 0, 0, 0}, {144, 192, 49}, {126, 110, 173}, {255, 255, 255}, { 0, 0, 0}, {234, 108, 21}, { 86, 168, 228}, {255, 255, 255}, { 0, 0, 0}, { 63, 55, 86}, { 72, 96, 25}, {255, 255, 255}, @@ -434,60 +446,39 @@ int main(int argc, char *argv[]){ } if (event.type == SDL_KEYDOWN) // a key has been pressed - switch (event.key.keysym.sym){ // EMULATOR CONTROL : - case SDLK_F1: // save disk 0 back to host - if (disk[0].filename[0] && !disk[0].readOnly){ - f = fopen(disk[0].filename, "wb"); - if (f){ - if (fwrite(disk[0].data, 1, 232960, f) != 232960){ - printf("Write failed\n"); - } - fclose(f); - } - } - break; + case SDLK_F1: saveFloppy(0); break; // save disk 0 back to host + case SDLK_F2: saveFloppy(1); break; // save disk 1 back to host - case SDLK_F2: // save disk 1 back to host - if (disk[1].filename[0] && !disk[1].readOnly){ - f = fopen(disk[1].filename, "wb"); - if (f){ - if (fwrite(disk[1].data, 1, 232960, f) != 232960){ - printf("Write failed\n"); - } - fclose(f); - } - } - break; - - case SDLK_F3: paused = !paused; break; // pause / un-pause - - case SDLK_F4: // paste txt from clipboard - if (SDL_HasClipboardText()){ - char *clipboardText = SDL_GetClipboardText(); - int c = 0; - while (clipboardText[c]){ // all chars until ascii NUL - KBD = clipboardText[c++] | 0x80; // set bit7 - if (KBD == 0x8A) KBD = 0x8D; // Line Feed to Carriage Ret - puce6502Exec(400000); // to process each char - } - SDL_free(clipboardText); - } - break; - - case SDLK_F5: if ((zoom-=2) < 0) zoom = 0; // zoom out - case SDLK_F6: if (++zoom > 8) zoom = 8; // zoom in + case SDLK_F3: if ((zoom-=2) < 0) zoom = 0; // zoom out + case SDLK_F4: if (++zoom > 8) zoom = 8; // zoom in SDL_SetWindowSize(wdo, 280*zoom, 192*zoom); - SDL_RenderSetScale(rdr, zoom, zoom); break; + SDL_RenderSetScale(rdr, zoom, zoom); + break; - case SDLK_F7: trimGC -= .01; break; // PDL Trim - case SDLK_F8: trimGC += .01; break; // PDL Trim + case SDLK_F5: trimGC -= .01; break; // PDL Trim + case SDLK_F6: trimGC += .01; break; // PDL Trim - case SDLK_F9: muted = !muted; break; // mute - case SDLK_F10: monochrome = !monochrome; break; // ... + case SDLK_F7: // paste txt from clipboard + if (SDL_HasClipboardText()){ + char *clipboardText = SDL_GetClipboardText(); + int c = 0; + while (clipboardText[c]){ // all chars until ascii NUL + KBD = clipboardText[c++] | 0x80; // set bit7 + if (KBD == 0x8A) KBD = 0x8D; // Line Feed to Carriage Ret + puce6502Exec(400000); // to process each char + } + SDL_free(clipboardText); + } + break; + + case SDLK_F8: muted = !muted; break; // mute + case SDLK_F9: monochrome = !monochrome; break; // ... + case SDLK_F10: paused = !paused; break; // pause / un-pause + case SDLK_F12: running = false; break; // goodbye case SDLK_F11: // reset if (ctrl) @@ -499,8 +490,6 @@ int main(int argc, char *argv[]){ } break; - case SDLK_F12: running = false; break; // goodbye - // EMULATED KEYS : case SDLK_ESCAPE: KBD = 0x9B; break; // ESC @@ -592,7 +581,7 @@ int main(int argc, char *argv[]){ word = (uint16_t)(ram[ vRamBase + offsetHGR[line] + col + 1 ]) << 8; // put the two next bytes into one word (in reverse order) word += ram[ vRamBase + offsetHGR[line] + col ]; // check if this group of 7 dots need a redraw (ie was modified) - if (previousDots[line][col] != word || !blink){ // or refresh the full screen every 1/2 second (everytime blink is reset to 0) + if (previousDots[line][col] != word || !frame){ // or refresh the full screen every 1 second for (bit=0; bit<16; bit++) bits[bit] = (word >> bit) & 1; // store all bits of the word into the 'bits' array @@ -680,7 +669,7 @@ int main(int argc, char *argv[]){ if (glyph > 0x5F) glyph &= 0x3F; // shifts to match if (glyph < 0x20) glyph |= 0x40; // the ASCII codes - if (glyphAttribute == A_NORMAL || blink < 15) + if (glyphAttribute == A_NORMAL || blink) SDL_RenderCopy(rdr, normCharTexture, &charRects[glyph], &dstRect); else SDL_RenderCopy(rdr, revCharTexture, &charRects[glyph], &dstRect); @@ -708,15 +697,14 @@ int main(int argc, char *argv[]){ } // else, skip frame frame++; - if (frameStart > reftime + 1000){ + if (frame > 30) blink = false; + if (frameStart >= reftime + 1000){ fps = (float)(frame * 1000.0) / (float)(frameStart - reftime); - // printf("TIME:%d FPS:%f FRAME:%d\n", frameStart - reftime, fps, frame); - frame = 0; reftime = SDL_GetTicks(); + frame = 0; + blink = true; } - if (++blink == 30) blink = 0; - } // while (running) //================================================ RELEASE RESSOURSES AND EXIT