From bb4c4f0f9a5bfc4fee067e14c7700b2155854a39 Mon Sep 17 00:00:00 2001 From: ArthurFerreira2 Date: Sun, 6 Sep 2020 00:40:24 +0200 Subject: [PATCH] v0.4 stable --- Makefile | 4 +- README.md | 45 +++-- puce6502.c | 77 +++++--- puce6502.h | 20 +- reinetteII+.c | 498 ++++++++++++++++++++++++++++-------------------- reinetteII+.rc | 8 +- reinetteII+.res | Bin 0 -> 62758 bytes 7 files changed, 391 insertions(+), 261 deletions(-) create mode 100644 reinetteII+.res diff --git a/Makefile b/Makefile index 32374dd..7e9408f 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = gcc -FLAGS = -std=c99 -pedantic -Wpedantic -Wall -O3 -Werror +FLAGS = -std=c99 -pedantic -Wpedantic -Wall -O3 LIBS = -lSDL2 # comment this line if you are under Linux : @@ -12,6 +12,6 @@ reinetteII+: reinetteII+.c puce6502.c $(WIN32-RES) $(CC) $^ $(FLAGS) $(WIN32-LIBS) $(LIBS) -o $@ reinetteII+.res: reinetteII+.rc - windres reinetteII+.rc -O coff -o $(WIN32-RES) + windres $^ -O coff -o $(WIN32-RES) all: reinetteII+ diff --git a/README.md b/README.md index 2fd9f57..b64dcb0 100644 --- a/README.md +++ b/README.md @@ -8,19 +8,20 @@ After [reinette](https://github.com/ArthurFerreira2/reinette) (Apple 1 emulator) \* 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.3b) +[download windows binaries](https://github.com/ArthurFerreira2/reinette-II-plus/releases/tag/0.4b) ### Featuring : * all video modes in color * mono sound with mute/unmute -* 48KB (no language card support) +* 64KB (language card support) * paddles/joystick with trim adjustment * paste text from clipboard * disk ][ adapter with two drives (.nib files only) * drag and drop .nib files to inset a floppy * save floppy changes back to host * screen scaling by integer increments +* easy screenshot It uses the same MOS 6502 CPU emulator as her sisters (now christened [puce6502](https://github.com/ArthurFerreira2/puce6502)).\ @@ -48,18 +49,28 @@ Pressing the ALT key while dropping the file inserts it into drive 2. 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 : zoom out down to 1:1 pixels -* F4 : zoom in, max 8x -* 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 +* F1 : display save how to +* ctrl F1 : writes the changes of the floppy in drive 0 back to host +* alt F1 : writes the changes of the floppy in drive 1 back to host +* F2 : save a screenshot into the screenshots directory +* F3 : paste text from clipboard +* F4 : mute / unmute sound +* shift F4 : increase volume +* ctrl F4 : decrease volume +* F5 : reset joystick release speed, +* shift F5 : increase joystick release speed +* crtl F5 : decrease joystick release speed, +* F6 : reset joystick action speed, +* shift F6 : increase joystick action speed +* crtl F6 : decrease joystick action speed, +* F7 : reset the zoom to 2:1 +* shift F7 : increase zoom up to 8:1 max +* ctrl F7 : decrease zoom down to 1:1 pixels +* F8 : monochrome / color display (only in HGR mode) +* F9 : pause / un-pause the emulator +* F10 : break +* F11 : reset +* F12 : about, help Paddles / Joystick : @@ -76,12 +87,12 @@ Paddles / Joystick : * ~~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 +* ~~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~~ - 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) +* ~~only has 48KB of RAM (can't run software requiring the language card)~~ * and many others ... ### To do @@ -91,7 +102,7 @@ Paddles / Joystick : * check for more accurate RGB values. * ~~implement color fringe effect in HGR~~ * ~~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. +* ~~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 diff --git a/puce6502.c b/puce6502.c index c94f7b0..cbb5417 100644 --- a/puce6502.c +++ b/puce6502.c @@ -1,5 +1,4 @@ /* - puce6502 - MOS 6502 cpu emulator Last modified 1st of August 2020 Copyright (c) 2018 Arthur Ferreira (arthur.ferreira2@gmail.com) @@ -27,15 +26,16 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ #include "puce6502.h" -#include // function to be provided by user to handle read and writes to locations not // in ROM or in RAM : Soft Switches, extension cards ROMs, PIA, VIA, ACIA etc... -extern uint8_t softSwitches(uint16_t address, uint8_t value); +extern uint8_t softSwitches(uint16_t address, uint8_t value, bool WRT); + +// these are the Language Card switches used in readMem and writeMem +extern bool LCWR, LCRD, LCBK2; #define CARRY 0x01 @@ -60,15 +60,7 @@ struct Register { } reg; -// instruction timing : -// http://nparker.llx.com/a2/opcodes.html -// http://wouter.bbcmicro.net/general/6502/6502_opcodes.html -// -// NOT IMPLEMENTED : -// Absolute-X, absolute-Y, and Zpage-Y addressing modes need an extra cycle -// if indexing crosses a page boundary, or if the instruction writes to memory. - -static int cycles[256] = { // cycle count per instruction +static int cycles[256] = { // cycles per instruction 7,6,0,0,0,3,5,0,3,2,2,0,0,4,6,0,3,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, 6,6,0,0,3,3,5,0,4,2,2,0,4,4,6,0,3,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, 6,6,0,0,0,3,5,0,3,2,2,0,3,4,6,0,3,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, @@ -83,14 +75,48 @@ static int cycles[256] = { // cycle count per instruction //=============================================================== MEMORY AND I/O inline static uint8_t readMem(uint16_t address){ - if (address < RAMSIZE) return(ram[address]); - if (address >= ROMSTART) return(rom[address - ROMSTART]); - return softSwitches(address, 0); // MEMORY MAPPED I/O + if (address < RAMSIZE) + return(ram[address]); // RAM + + if (address >= ROMSTART){ + if (!LCRD) + return(rom[address - ROMSTART]); // ROM + + if (LCBK2 && (address < 0xE000)) + return(bk2[address - BK2START]); // BK2 + + return(lgc[address - LGCSTART]); // LC + } + + if ((address & 0xFF00) == SL6START) + return(sl6[address - SL6START]); // disk][ + + if (address == 0xCFFF || ((address & 0xFF00) == 0xC000)) + return(softSwitches(address, 0, false)); + + return(ticks % 256); // catch all, give a 'floating' value } + inline static void writeMem(uint16_t address, uint8_t value){ - if (address < RAMSIZE) ram[address] = value; - else if (address < ROMSTART) softSwitches(address, value); + if (address < RAMSIZE) { + ram[address] = value; // RAM + return; + } + + if (LCWR && (address >= ROMSTART)){ + if (LCBK2 && (address < 0xE000)){ + bk2[address - BK2START] = value; // BK2 + return; + } + lgc[address - LGCSTART] = value; // LC + return; + } + + if (address == 0xCFFF || ((address & 0xFF00) == 0xC000)){ + softSwitches(address, value, true); // Soft Switches + return; + } } @@ -117,7 +143,7 @@ inline static void branch(){ // used by the 8 branch instructions reg.PC += ope.address; } -inline static void makeUpdates(uint8_t val){ // used by ASL, LSR, ROL and ROR +inline static void makeUpdates(uint8_t val){ // used by ASL, LSR, ROL and ROR if (ope.setAcc){ reg.A = val; ope.setAcc = false; @@ -153,6 +179,7 @@ static void ZPX(){ // Zero Page,X } static void ZPY(){ // Zero Page,Y + if (readMem(reg.PC) + reg.Y > 0xFF) ticks++; ope.address = (readMem(reg.PC++) + reg.Y) & 0xFF; ope.value = readMem(ope.address); } @@ -169,12 +196,14 @@ static void ABS(){ // ABSolute } static void ABX(){ // ABsolute,X + if (readMem(reg.PC) + reg.X > 0xFF) ticks++; ope.address = (readMem(reg.PC) | (readMem(reg.PC + 1) << 8)) + reg.X; ope.value = readMem(ope.address); reg.PC += 2; } static void ABY(){ // ABsolute,Y + if (readMem(reg.PC) + reg.Y > 0xFF) ticks++; ope.address = (readMem(reg.PC) | (readMem(reg.PC + 1) << 8)) + reg.Y; ope.value = readMem(ope.address); reg.PC += 2; @@ -212,7 +241,7 @@ void BRK(){ // BReaK push(reg.PC & 0xFF); push(reg.SR | BREAK); reg.SR |= INTR; - reg.PC = readMem(0xFFFE) | (readMem(0xFFFF) << 8); + reg.PC = readMem(0xFFFE) | ((readMem(0xFFFF) << 8)); // IRQ/BRK FFFE FFFF } static void CLD(){ // CLear Decimal @@ -532,7 +561,7 @@ static void (*addressing[])(void) = { //========================================================= USER INTERFACE (API) void puce6502Reset(){ - reg.PC = readMem(0xFFFC) | (readMem(0xFFFD) << 8); + reg.PC = readMem(0xFFFC) | (readMem(0xFFFD) << 8); // RESET FFFC FFFD reg.SP = 0xFF; reg.SR = (reg.SR | INTR) & ~DECIM; ope.setAcc = false; @@ -552,10 +581,6 @@ void puce6502Exec(long long int cycleCount){ //=================================================== ADDED FOR REINETTE II PLUS -void puce6502Break() { +void puce6502Break(){ BRK(); } - -void puce6502Goto(uint16_t address) { - reg.PC = address; -} diff --git a/puce6502.h b/puce6502.h index 01f22ea..3ede70f 100644 --- a/puce6502.h +++ b/puce6502.h @@ -30,25 +30,33 @@ */ -#ifndef _CPU_H -#define _CPU_H +#ifndef _PUCE6502_H +#define _PUCE6502_H typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef enum {false, true} bool; +#define RAMSIZE 0xC000 #define ROMSTART 0xD000 #define ROMSIZE 0x3000 -#define RAMSIZE 0xC000 +#define LGCSTART 0xD000 +#define LGCSIZE 0x3000 +#define BK2START 0xD000 +#define BK2SIZE 0x1000 +#define SL6START 0xC600 +#define SL6SIZE 0x00FF -uint8_t rom[ROMSIZE]; -uint8_t ram[RAMSIZE]; +uint8_t ram[RAMSIZE]; // 48K of ram in $000-$BFFF +uint8_t rom[ROMSIZE]; // 12K of rom in $D000-$FFFF +uint8_t lgc[LGCSIZE]; // Language Card 12K in $D000-$FFFF +uint8_t bk2[BK2SIZE]; // bank 2 of Language Card 4K in $D000-$DFFF +uint8_t sl6[SL6SIZE]; // P5A disk ][ PROM in slot 6 long long int ticks; void puce6502Exec(long long int cycleCount); void puce6502Reset(); void puce6502Break(); -void puce6502Goto(uint16_t address); #endif diff --git a/reinetteII+.c b/reinetteII+.c index 16e58df..f509225 100644 --- a/reinetteII+.c +++ b/reinetteII+.c @@ -1,31 +1,30 @@ /* + reinette II plus, a french Apple II emulator, using SDL2 + and powered by puce6502 - a MOS 6502 cpu emulator by the same author + Last modified 5th of September 2020 + Copyright (c) 2020 Arthur Ferreira (arthur.ferreira2@gmail.com) - reinette II plus, a french Apple II emulator, using SDL2 - and powered by puce6502 - a MOS 6502 cpu emulator by the same author - Last modified 13th of August 2020 - Copyright (c) 2020 Arthur Ferreira (arthur.ferreira2gmail.com) + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ #include +#include #include #include "puce6502.h" @@ -33,12 +32,14 @@ //================================================================ SOFT SWITCHES uint8_t KBD = 0; // $C000, $C010 ascii value of keyboard input -bool SPKR = false; // $C030 Speaker toggle bool TEXT = true; // $C050 CLRTEXT / $C051 SETTEXT bool MIXED = false; // $C052 CLRMIXED / $C053 SETMIXED uint8_t PAGE = 1; // $C054 PAGE1 / $C055 PAGE2 bool HIRES = false; // $C056 GR / $C057 HGR - +bool LCWR = true; // Language Card writable +bool LCRD = false; // Language Card readable +bool LCBK2 = true; // Language Card bank 2 enabled +bool LCWFF = false; // Language Card pre-write flip flop //====================================================================== PADDLES @@ -46,28 +47,27 @@ uint8_t PB0 = 0; uint8_t PB1 = 0; // $C062 Push Button 1 (bit 7) / Solid Apple uint8_t PB2 = 0; // $C063 Push Button 2 (bit 7) / shift mod !!! float GCP[2] = {127, 127}; // GC Position ranging from 0 (left) to 255 right -float GCC[2] = {0}; // GC0 and GC1 Countdown +float GCC[2] = {0}; // $C064 (GC0) and $C065 (GC1) Countdowns int GCD[2] = {0}; // GC0 and GC1 Directions (left/down or right/up) int GCA[2] = {0}; // GC0 and GC1 Action (push or release) -uint8_t GCActionSpeed = 16; // Game Controller speed at which it goes to the edges -uint8_t GCReleaseSpeed = 16; // Game Controller speed at which it returns to center -const float GCFreq = 0.15; // the freq at which the 556 timer decreases the GC values -long long int GCCrigger; // the tick at which the GCs have been reseted +uint8_t GCActionSpeed = 8; // Game Controller speed at which it goes to the edges +uint8_t GCReleaseSpeed = 8; // Game Controller speed at which it returns to center +long long int GCCrigger; // $C070 the tick at which the GCs were reseted - -inline float paddle(int pdl){ - GCC[pdl] -= (ticks - GCCrigger) * GCFreq; - if (GCC[pdl] < 0) GCC[pdl] = 0; - return(GCC[pdl]); +inline static void resetPaddles(){ + GCC[0] = GCP[0] * GCP[0]; // initialize the countdown for both paddles + GCC[1] = GCP[1] * GCP[1]; // to the square of their actuall values (positions) + GCCrigger = ticks; // records the time this was done } -inline void resetPaddles(){ - GCC[0] = GCP[0] * GCP[0]; - GCC[1] = GCP[1] * GCP[1]; - GCCrigger = ticks; +inline static uint8_t readPaddle(int pdl){ + const float GCFreq = 6.6; // the speed at which the GC values decrease + GCC[pdl] -= (ticks - GCCrigger) / GCFreq; // decreases the countdown + if (GCC[pdl] <= 0) // timeout + return(GCC[pdl] = 0); // returns 0 + return(0x80); // not timeout, return something with the MSB set } - //======================================================================== AUDIO #define audioBufferSize 4096 // found to be large enought @@ -75,14 +75,25 @@ Sint8 audioBuffer[2][audioBufferSize] = {0}; SDL_AudioDeviceID audioDevice; bool muted = false; // mute/unmute +static void playSound(){ + static long long int lastTick = 0LL; + static bool SPKR = false; // $C030 Speaker toggle + + if (!muted){ + SPKR = !SPKR; // toggle speaker state + Uint32 length = (ticks - lastTick) / 10.65625; // 1023000Hz / 96000Hz = 10.65625 + lastTick = ticks; + if (length > audioBufferSize) length = audioBufferSize; + SDL_QueueAudio(audioDevice, audioBuffer[SPKR], length | 1); // | 1 TO HEAR HIGH FREQ SOUNDS + } +} //====================================================================== DISK ][ -uint8_t slot6[256] = {0}; // P5A disk ][ PROM in slot 6 -int curDrv = 0; // only one can be enabled at a time +int curDrv = 0; // Current Drive - only one can be enabled at a time struct drive{ - char filename[512]; // the full disk image path + char filename[400]; // the full disk image pathname bool readOnly; // based on the image file attributes uint8_t data[232960]; // nibblelized disk image bool motorOn; // motor status @@ -93,58 +104,52 @@ struct drive{ int insertFloppy(SDL_Window *wdo, char *filename, int drv){ - int i, a, b; - char title[1024]; - - FILE *f = fopen(filename, "rb"); // open it in read binary - if (!f){ - printf("Could not open %s\n", filename); + FILE *f = fopen(filename, "rb"); // open file in read binary mode + if (!f || fread(disk[drv].data, 1, 232960, f) != 232960) // load it into memory and check size return(0); - } - if (fread(disk[drv].data, 1, 232960, f) != 232960){ // load it into memory and check size - printf("Floppy image should be exactly 232960 Bytes long\n"); - return(0); - } fclose(f); - sprintf(disk[drv].filename,"%s", filename); // update disk filename + sprintf(disk[drv].filename,"%s", filename); // update disk filename record - f = fopen(filename, "ab"); // check if file is writeable - if (f){ - disk[drv].readOnly = false; // f will be NULL if open in W failed - fclose(f); + f = fopen(filename, "ab"); // try to open the file in append binary mode + if (!f){ // success, file is writable + disk[drv].readOnly = true; // update the readOnly flag + fclose(f); // and close it untouched } - else disk[drv].readOnly = true; + else disk[drv].readOnly = false; // f is NULL, no writable, no need to close it + char title[1000]; // UPDATE WINDOW TITLE + int i, a, b; i = a = 0; while (disk[0].filename[i] != 0) // find start of filename for disk0 if (disk[0].filename[i++] == '\\') a = i; - i = b = 0; while (disk[1].filename[i] != 0) // find start of filename for disk1 if (disk[1].filename[i++] == '\\') b = i; - sprintf(title, "reinette II+ D1: %s D2: %s", disk[0].filename + a, \ - disk[1].filename + b); + sprintf(title, "reinette II+ D1: %s D2: %s", \ + disk[0].filename + a, disk[1].filename + b); SDL_SetWindowTitle(wdo, title); // updates window title return(1); } + int saveFloppy(int drive){ - if (disk[drive].filename[0] && !disk[drive].readOnly){ // is there's a floppy ? is it writable ? - FILE *f = fopen(disk[drive].filename, "wb"); - if (f){ // open in write/binary succeeded - if (fwrite(disk[drive].data, 1, 232960, f) != 232960){ // check we could write the full lenght - printf("Write failed\n"); - return(0); // failed to write - } - fclose(f); // release the ressource - } + if (!disk[drive].filename[0]) return 0; // no file loaded into drive + if (disk[drive].readOnly) return 0; // file is read only write no aptempted + + FILE *f = fopen(disk[drive].filename, "wb"); + if (!f) return(0); // could not open the file in write overide binary + if (fwrite(disk[drive].data, 1, 232960, f) != 232960){ // failed to write the full file (disk full ?) + fclose(f); // release the ressource + return(0); } - return(1); // success + fclose(f); // success, release the ressource + return (1); } + void stepMotor(uint16_t address){ static bool phases[2][4] = {0}; // phases states (for both drives) static bool phasesB[2][4] = {0}; // phases states Before @@ -157,9 +162,9 @@ void stepMotor(uint16_t address){ int phase = address >> 1; phasesBB[curDrv][pIdxB[curDrv]] = phasesB[curDrv][pIdxB[curDrv]]; - phasesB[curDrv][pIdx[curDrv]] = phases[curDrv][pIdx[curDrv]]; + phasesB[curDrv][pIdx[curDrv]] = phases[curDrv][pIdx[curDrv]]; pIdxB[curDrv] = pIdx[curDrv]; - pIdx[curDrv] = phase; + pIdx[curDrv] = phase; if (!(address & 1)){ // head not moving (PHASE x OFF) phases[curDrv][phase] = false; @@ -178,31 +183,25 @@ void stepMotor(uint16_t address){ } +void setDrv(bool drv){ + disk[drv].motorOn = disk[!drv].motorOn || disk[drv].motorOn; // if any of the motors were ON + disk[!drv].motorOn = false; // motor of the other drive is set to OFF + curDrv = drv; // set the current drive +} + //========================================== MEMORY MAPPED SOFT SWITCHES HANDLER // this function is called from readMem and writeMem in puce6502 // it complements both functions when address 1is between 0xC000 and 0xCFFF - -uint8_t softSwitches(uint16_t address, uint8_t value){ - static uint8_t dLatch = 0; // disk ][ I/O reg - static long long int lastTick = 0LL; - - if ((address >> 8) == 0xC6) return(slot6[address - 0xC600]); // disk ][ PROM +uint8_t softSwitches(uint16_t address, uint8_t value, bool WRT){ + static uint8_t dLatch = 0; // disk ][ I/O register switch (address){ case 0xC000: return(KBD); // KEYBOARD - case 0xC010: KBD &= 0x7F; return(KBD); // key STROBE + case 0xC010: KBD &= 0x7F; return(KBD); // KBDSTROBE - case 0xC020: // TAPEOUT (shall we listen it ?) + case 0xC020: // TAPEOUT (shall we listen it ? - try SAVE from applesoft) case 0xC030: // SPEAKER - case 0xC033: // apple invader uses it to output sound ! - if (!muted){ - SPKR = !SPKR; // toggle speaker state - Uint32 length = (ticks - lastTick) / 10.65625; // 1023000Hz / 96000Hz = 10.65625 - lastTick = ticks; - if (length > audioBufferSize) length = audioBufferSize; - SDL_QueueAudio(audioDevice, audioBuffer[SPKR], length | 1); // | 1 TO HEAR HIGH FREQ SOUNDS - } - break; + case 0xC033: playSound(); break; // apple invader uses $C033 to output sound ! case 0xC050: TEXT = false; break; // Graphics case 0xC051: TEXT = true; break; // Text @@ -216,39 +215,28 @@ uint8_t softSwitches(uint16_t address, uint8_t value){ case 0xC061: return(PB0); // Push Button 0 case 0xC062: return(PB1); // Push Button 1 case 0xC063: return(PB2); // Push Button 2 - case 0xC064: return(paddle(0) != 0 ? 0x80: 0x00); // Paddle 0 - case 0xC065: return(paddle(1) != 0 ? 0x80: 0x00); // Paddle 1 + case 0xC064: return(readPaddle(0)); // Paddle 0 + case 0xC065: return(readPaddle(1)); // Paddle 1 + case 0xC066: return(readPaddle(0)); // Paddle 2 -- not implemented + case 0xC067: return(readPaddle(1)); // Paddle 3 -- not implemented + case 0xC070: resetPaddles(); break; // paddle timer RST - case 0xC0E0: // PHASE0OFF - case 0xC0E1: // PHASE0ON - case 0xC0E2: // PHASE1OFF - case 0xC0E3: // PHASE1ON - case 0xC0E4: // PHASE2OFF - case 0xC0E5: // PHASE2ON - case 0xC0E6: // PHASE3OFF - case 0xC0E7: stepMotor(address); break; // PHASE3ON + case 0xC0E0 ... 0xC0E7: stepMotor(address); break; // MOVE DRIVE HEAD + case 0xCFFF: case 0xC0E8: disk[curDrv].motorOn = false; break; // MOTOROFF case 0xC0E9: disk[curDrv].motorOn = true; break; // MOTORON - case 0xC0EA: // DRIVE0EN - disk[0].motorOn = disk[1].motorOn || disk[0].motorOn; - disk[1].motorOn = false; - curDrv = 0; - break; - case 0xC0EB: // DRIVE1EN - disk[1].motorOn = disk[0].motorOn || disk[1].motorOn; - disk[0].motorOn = false; - curDrv = 1; - break; + case 0xC0EA: setDrv(0); break; // DRIVE0EN + case 0xC0EB: setDrv(1); break; // DRIVE1EN case 0xC0EC: // Shift Data Latch if (disk[curDrv].writeMode) // writting disk[curDrv].data[disk[curDrv].track*0x1A00+disk[curDrv].nibble]=dLatch; else // reading dLatch=disk[curDrv].data[disk[curDrv].track*0x1A00+disk[curDrv].nibble]; - disk[curDrv].nibble = (disk[curDrv].nibble + 1) % 0x1A00; // turn floppy + disk[curDrv].nibble = (disk[curDrv].nibble + 1) % 0x1A00; // turn floppy of 1 nibble return(dLatch); case 0xC0ED: dLatch = value; break; // Load Data Latch @@ -259,74 +247,95 @@ uint8_t softSwitches(uint16_t address, uint8_t value){ case 0xC0EF: disk[curDrv].writeMode = true; break; // latch for WRITE - // default: printf("Uncaught Soft Switch access at %04X\n", address); + case 0xC080: // LANGUAGE CARD : + case 0xC084: LCBK2 = 1; LCRD = 1; LCWR = 0; LCWFF = 0; break; // LC2RD + case 0xC081: + case 0xC085: LCBK2 = 1; LCRD = 0; LCWR|=LCWFF; LCWFF = !WRT; break; // LC2WR + case 0xC082: + case 0xC086: LCBK2 = 1; LCRD = 0; LCWR = 0; LCWFF = 0; break; // ROMONLY2 + case 0xC083: + case 0xC087: LCBK2 = 1; LCRD = 1; LCWR|=LCWFF; LCWFF = !WRT; break; // LC2RW + case 0xC088: + case 0xC08C: LCBK2 = 0; LCRD = 1; LCWR = 0; LCWFF = 0; break; // LC1RD + case 0xC089: + case 0xC08D: LCBK2 = 0; LCRD = 0; LCWR|=LCWFF; LCWFF = !WRT; break; // LC1WR + case 0xC08A: + case 0xC08E: LCBK2 = 0; LCRD = 0; LCWR = 0; LCWFF = 0; break; // ROMONLY1 + case 0xC08B: + case 0xC08F: LCBK2 = 0; LCRD = 1; LCWR|=LCWFF; LCWFF = !WRT; break; // LC1RW } - - return(0); // catch all + return(ticks%256); // catch all } - //========================================================== PROGRAM ENTRY POINT int main(int argc, char *argv[]){ + char workDir[1000]; // find the working directory + int workDirSize = 0, i = 0; + while (argv[0][i] != '\0'){ + workDir[i] = argv[0][i]; + if (argv[0][++i] == '\\') workDirSize = i + 1; // find the last '/' if any + } + // SDL INITIALIZATION + double fps = 60, frameTime = 0, frameDelay = 1000.0 / 60.0; // targeting 60 FPS + Uint32 frameStart = 0, frame = 0; int zoom = 2; - const double frameDelay = 1000.0 / 60.0; // targeting 60 FPS - double fps = 60; - Uint32 frameStart = 0, frameTime = 0, frame = 0; uint8_t tries = 0; // disk ][ speed-up SDL_Event event; SDL_bool paused = false, running = true, ctrl, shift, alt; - if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "[DEBUG] > %s", SDL_GetError()); + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0){ + printf("failed to initialize SDL2 : %s", SDL_GetError()); return(-1); } - SDL_EventState(SDL_DROPFILE, SDL_ENABLE); + SDL_EventState(SDL_DROPFILE, SDL_ENABLE); // ask SDL2 to read dropfile events SDL_Window *wdo = SDL_CreateWindow("reinette II+", SDL_WINDOWPOS_CENTERED, \ SDL_WINDOWPOS_CENTERED, 280*zoom, 192*zoom, SDL_WINDOW_OPENGL); - + SDL_Surface *sshot; // used later for the screenshots SDL_Renderer *rdr = SDL_CreateRenderer(wdo, -1, SDL_RENDERER_ACCELERATED); // | SDL_RENDERER_PRESENTVSYNC); SDL_SetRenderDrawBlendMode(rdr, SDL_BLENDMODE_NONE); // SDL_BLENDMODE_BLEND); SDL_RenderSetScale(rdr, zoom, zoom); - // SDL AUDIO INITIALIZATION SDL_AudioSpec desired = {96000, AUDIO_S8, 1, 0, 4096, 0, 0, NULL, NULL}; - audioDevice = SDL_OpenAudioDevice(NULL, 0, &desired, NULL, SDL_FALSE); - SDL_PauseAudioDevice(audioDevice, muted); + audioDevice = SDL_OpenAudioDevice(NULL, 0, &desired, NULL, SDL_FALSE); // get the audio device ID + SDL_PauseAudioDevice(audioDevice, muted); // unmute it (muted is false) + uint8_t volume = 2; for (int i=1; i 1) insertFloppy(wdo, argv[1], 0); // load .nib in parameter into drive 0 - if (argc > 1) insertFloppy(wdo, argv[1], 0); // load .nib in parameter into drive 0 + for (int i=0; i 8) zoom = 8; // zoom in - SDL_SetWindowSize(wdo, 280 * zoom, 192 * zoom); - SDL_RenderSetScale(rdr, zoom, zoom); + case SDLK_F1: // SAVES + if (ctrl){ + if (saveFloppy(0)) + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Save", "\nDisk 1 saved back to file\n", NULL); + else + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Save", "\nThere was an error while saving Disk 1\n", NULL); + } + else if (alt){ + if (saveFloppy(1)) + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Save", "\nDisk 2 saved back to file\n", NULL); + else + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Save", "\nThere was an error while saving Disk 2\n", NULL); + } + else + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Save", "ctrl F1 to save D1\nalt F1 to save D2\n", NULL); break; - case SDLK_F5: if (GCReleaseSpeed > 1 ) GCReleaseSpeed -= 2; break; // PDL Trim - case SDLK_F6: if (GCReleaseSpeed < 127) GCReleaseSpeed += 2; break; // PDL Trim - 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 + case SDLK_F2: { // SCREENSHOTS + sshot = SDL_GetWindowSurface(wdo); + SDL_RenderReadPixels(rdr, NULL, SDL_GetWindowPixelFormat(wdo), sshot->pixels, sshot->pitch); + workDir[workDirSize]=0; + int i = -1, a = 0, b = 0; + while (disk[0].filename[++i] != '\0'){ + if (disk[0].filename[i] == '\\') a = i; + if (disk[0].filename[i] == '.') b = i; } - SDL_free(clipboardText); + strncat(workDir, "screenshots", 13); + if (a != b) strncat(workDir, disk[0].filename + a, b - a); + else strncat(workDir,"\\no disk", 10); + strncat(workDir, ".bmp", 5); + SDL_SaveBMP(sshot, workDir); + SDL_FreeSurface(sshot); + break; } - 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) - puce6502Break(); - else { - puce6502Reset(); - softSwitches(0xC0E9,0); // drive0En - softSwitches(0xC0E8,0); // motorOff + case SDLK_F3: // PASTE text 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; // translate Line Feed to Carriage Ret + puce6502Exec(400000); // give cpu (and applesoft) some cycles to process each char + } + SDL_free(clipboardText); // release the ressource } break; + case SDLK_F4: // VOLUME + if (shift && (volume < 120)) volume++; // increase volume + if (ctrl && (volume > 0)) volume--; // decrease volume + if (!ctrl && !shift) muted = !muted; // toggle mute / unmute + for (int i=1; i 1 )) GCReleaseSpeed -= 2; // decrease Release Speed + if (!ctrl && !shift) GCReleaseSpeed = 8; // reset Release Speed to 8 + break; + + case SDLK_F6: // JOYSTICK Action Speed + if (shift && (GCActionSpeed < 127)) GCActionSpeed += 2; // increase Action Speed + if (ctrl && (GCActionSpeed > 1 )) GCActionSpeed -= 2; // decrease Action Speed + if (!ctrl && !shift) GCActionSpeed = 8; // reset Action Speed to 8 + break; + + case SDLK_F7: // ZOOM + if (shift && (zoom < 8)) zoom++; // zoom in + if (ctrl && (zoom > 1)) zoom--; // zoom out + if (!ctrl && !shift) zoom = 2; // reset zoom to 2 + SDL_SetWindowSize(wdo, 280 * zoom, 192 * zoom); // update window size + SDL_RenderSetScale(rdr, zoom, zoom); // update renderer size + break; + + case SDLK_F8: monochrome = !monochrome; break; // toggle monochrome for HGR mode + case SDLK_F9: paused = !paused; break; // toggle pause + case SDLK_F10: puce6502Break(); // simulate a break + case SDLK_F11: puce6502Reset(); // reset + + case SDLK_F12: // help box + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Help", + "~ reinette II plus v0.4b ~ \ + \n\nctrl F1\twrites the changes of the floppy in drive 0 \ + \nalt F1\twrites the changes of the floppy in drive 1 \ + \n\nF2\tsave a screenshot into the screenshots directory \ + \nF3\tpaste text from clipboard \ + \n\nF4\tmute / un-mute sound \ + \nshift F4\tincrease volume \ + \nctrl F4\tdecrease volume \ + \n\nF5\treset joystick release speed \ + \nshift F5\tincrease joystick release speed \ + \ncrtl F5\tdecrease joystick release speed \ + \n\nF6\treset joystick action speed \ + \nshift F6\tincrease joystick action speed \ + \ncrtl F6\tdecrease joystick action speed \ + \n\nF7\treset the zoom to 2:1 \ + \nshift F7\tincrease zoom up to 8:1 max \ + \nctrl F7\tdecrease zoom down to 1:1 pixels \ + \nF8\tmonochrome / color display (only in HGR) \ + \nF9\tpause / un-pause the emulator \ + \n\nF10\tload binary file into $8000 \ + \nF11\treset \ + \nctrl F11\tbreak \ + \n\nF12\tthis help \ + \n\nmore information at github.com/ArthurFerreira2", NULL); + break; + // EMULATED KEYS : case SDLK_a: KBD = ctrl ? 0x81: 0xC1; break; // a @@ -514,10 +600,10 @@ int main(int argc, char *argv[]){ case SDLK_j: KBD = ctrl ? 0x8A: 0xCA; break; // j LF case SDLK_k: KBD = ctrl ? 0x8B: 0xCB; break; // k VTAB case SDLK_l: KBD = ctrl ? 0x8C: 0xCC; break; // l FF - case SDLK_m: KBD = ctrl ? 0x8D: 0xCD; break; // m CR - case SDLK_n: KBD = ctrl ? 0x8E: 0xCE; break; // n + case SDLK_m: KBD = ctrl ? shift ? 0x9D: 0x8D: 0xCD; break; // m CR ] + case SDLK_n: KBD = ctrl ? shift ? 0x9E: 0x8E: 0xCE; break; // n ^ case SDLK_o: KBD = ctrl ? 0x8F: 0xCF; break; // o - case SDLK_p: KBD = ctrl ? 0x90: 0xD0; break; // p + case SDLK_p: KBD = ctrl ? shift ? 0x80: 0x90: 0xD0; break; // p @ case SDLK_q: KBD = ctrl ? 0x91: 0xD1; break; // q case SDLK_r: KBD = ctrl ? 0x92: 0xD2; break; // r case SDLK_s: KBD = ctrl ? 0x93: 0xD3; break; // s ESC @@ -528,7 +614,6 @@ int main(int argc, char *argv[]){ case SDLK_x: KBD = ctrl ? 0x98: 0xD8; break; // x CANCEL case SDLK_y: KBD = ctrl ? 0x99: 0xD9; break; // y case SDLK_z: KBD = ctrl ? 0x9A: 0xDA; break; // z - case SDLK_RETURN: KBD = ctrl ? 0x8A: 0x8D; break; // LF CR case SDLK_LEFTBRACKET: KBD = ctrl ? 0x9B: 0xDB; break; // [ { case SDLK_BACKSLASH: KBD = ctrl ? 0x9C: 0xDC; break; // \ | case SDLK_RIGHTBRACKET: KBD = ctrl ? 0x9D: 0xDD; break; // ] } @@ -554,7 +639,8 @@ int main(int argc, char *argv[]){ case SDLK_LEFT: KBD = 0x88; break; // BS case SDLK_RIGHT: KBD = 0x95; break; // NAK case SDLK_SPACE: KBD = 0xA0; break; - case SDLK_ESCAPE: KBD = 0x9B; break; + case SDLK_ESCAPE: KBD = 0x9B; break; // ESC + case SDLK_RETURN: KBD = 0x8D; break; // CR // EMULATED JOYSTICK : @@ -574,7 +660,7 @@ int main(int argc, char *argv[]){ } for (int pdl=0; pdl<2; pdl++){ // update the two paddles positions - if (GCA[pdl]) { // actively pushing the stick + if (GCA[pdl]){ // actively pushing the stick GCP[pdl] += GCD[pdl] * GCActionSpeed; if (GCP[pdl] > 255) GCP[pdl] = 255; if (GCP[pdl] < 0 ) GCP[pdl] = 0; @@ -711,12 +797,12 @@ int main(int argc, char *argv[]){ if (++frame > 30) frame = 0; frameTime = SDL_GetTicks() - frameStart; // frame duration - if (frameTime < frameDelay) { // do we have time ? + if (frameTime < frameDelay){ // do we have time ? SDL_Delay(frameDelay - frameTime); // wait 'vsync' SDL_RenderPresent(rdr); // swap buffers frameTime = SDL_GetTicks() - frameStart; // update frameTime - } - fps = (frameDelay / (double)frameTime) * 60.0; // calculate the actual frame rate + } // else skip the frame + fps = 1000.0 / frameTime; // calculate the actual frame rate } // while (running) diff --git a/reinetteII+.rc b/reinetteII+.rc index c5e1ed0..fcfc903 100644 --- a/reinetteII+.rc +++ b/reinetteII+.rc @@ -1,7 +1,7 @@ 1 ICON "assets/reinetteII+.ico" 1 VERSIONINFO -FILEVERSION 0,3,1,0 -PRODUCTVERSION 0,3,0,0 +FILEVERSION 0,4,1,0 +PRODUCTVERSION 0,4,0,0 BEGIN BLOCK "StringFileInfo" BEGIN @@ -9,12 +9,12 @@ BEGIN BEGIN VALUE "CompanyName", "Arthur Ferreira" VALUE "FileDescription", "Apple II+ emulator" - VALUE "FileVersion", "0.3.1.0" + VALUE "FileVersion", "0.4.1.0" VALUE "InternalName", "reinette II plus" VALUE "LegalCopyright", "Arthur Ferreira" VALUE "OriginalFilename", "reinetteII+.exe" VALUE "ProductName", "reinette II plus" - VALUE "ProductVersion", "0.3" + VALUE "ProductVersion", "0.4" END END BLOCK "VarFileInfo" diff --git a/reinetteII+.res b/reinetteII+.res new file mode 100644 index 0000000000000000000000000000000000000000..9ba786629dc84682a957c989bba4e9df8b424285 GIT binary patch literal 62758 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 B237z7 literal 0 HcmV?d00001