]> Shamusworld >> Repos - apple2/commitdiff
Undoing changes (accidentally) committed from r31.
authorShamus Hammons <jlhamm@acm.org>
Tue, 29 May 2007 05:16:51 +0000 (05:16 +0000)
committerShamus Hammons <jlhamm@acm.org>
Tue, 29 May 2007 05:16:51 +0000 (05:16 +0000)
16 files changed:
Makefile
apple2.cfg
src/apple2.cpp
src/ay8910.cpp
src/gui/button.cpp
src/gui/button.h
src/gui/draggablewindow.cpp
src/gui/element.cpp
src/gui/element.h
src/gui/gui.cpp
src/gui/gui.h
src/gui/guimisc.cpp
src/gui/guimisc.h
src/gui/textedit.cpp
src/gui/window.cpp
src/v65c02.cpp

index 24e7642c3d6ecce7f946850ebb308515ad60a40a..e94b4a61eed517abc5adf25ffeeacdeda8a231fc 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -54,9 +54,9 @@ TARGET     = apple2
 #              -ffast-math -fomit-frame-pointer `sdl-config --cflags` -fprofile-arcs -ftest-coverage
 # No optimization for profiling with gprof...
 CFLAGS   = -MMD -Wall -Wno-switch -D$(SYSTYPE) \
-               -ffast-math `sdl-config --cflags` -pg
+               -ffast-math `sdl-config --cflags` -pg -g
 CPPFLAGS = -MMD -Wall -Wno-switch -Wno-non-virtual-dtor -D$(SYSTYPE) \
-               -ffast-math `sdl-config --cflags` -pg
+               -ffast-math `sdl-config --cflags` -pg -g
 #              -fomit-frame-pointer `sdl-config --cflags` -g
 #              -fomit-frame-pointer `sdl-config --cflags` -DLOG_UNMAPPED_MEMORY_ACCESSES
 
@@ -73,6 +73,7 @@ INCS = -I. -I./src -I/usr/local/include -I/usr/include
 OBJS = \
        obj/button.o          \
        obj/draggablewindow.o \
+       obj/draggablewindow2.o \
        obj/element.o         \
        obj/gui.o             \
        obj/guimisc.o         \
index 197823747a18a0f634765c4a8585e32657aafd69..ece7b9ce5bb89ebb796a6a12c3e126ee8d16eeba 100755 (executable)
@@ -39,7 +39,7 @@ autoSaveState = 1
 # Yes, keys???
 #floppyImage1 = ./disks/MidnightMagic_etc.dsk
 # ???
-floppyImage1 = ./disks/battle_chess_1.dsk
+#floppyImage1 = ./disks/battle_chess_1.dsk
 # Yes 
 #floppyImage1 = ./disks/MoebiusI-1.dsk
 # Yes, but crashes on the attract mode
@@ -54,8 +54,8 @@ floppyImage1 = ./disks/battle_chess_1.dsk
 #floppyImage1 = ./disks/ultima_ii-1.dsk
 #floppyImage2 = ./disks/ultima_ii-2.dsk
 # Yes, autoloads!
-#floppyImage1 = ./disks/u2prog-patched.dsk
-#floppyImage2 = ./disks/u2player-jlh.dsk
+floppyImage1 = ./disks/u2prog-patched.dsk
+floppyImage2 = ./disks/u2player-jlh.dsk
 
 
 # OpenGL options: 1 - use OpenGL rendering, 0 - use old style rendering
index 7621a2e679edfefe1fb8393a5f59ebacf3b23678..dbdb619287e5d4de84e1b13fc405616c8bbeadb1 100755 (executable)
@@ -51,7 +51,7 @@
 
 #include "gui/gui.h"
 #include "gui/window.h"
-#include "gui/draggablewindow.h"
+#include "gui/draggablewindow2.h"
 #include "gui/textedit.h"
 
 using namespace std;
@@ -98,7 +98,7 @@ static void BlinkTimer(void);
 
 Element * TestWindow(void)
 {
-       Element * win = new DraggableWindow(10, 10, 128, 128);
+       Element * win = new DraggableWindow2(10, 10, 128, 128);
 //     ((DraggableWindow *)win)->AddElement(new TextEdit(4, 16, 92, 0, "u2prog.dsk", win));
 
        return win;
@@ -316,28 +316,28 @@ if (addr >= 0xC080 && addr <= 0xC08F)
 A-9 (Mockingboard)
 APPENDIX F Assembly Language Program Listings
 
-1      *PRIMARY ROUTINES
-2      *FOR SLOT 4
-3      *
-4                      ORG     $9000
-5      *                               ;ADDRESSES
-                                       FOR FIRST
-                                       6522
-6      ORB             EQU     $C400           ;PORT B
-7      ORA             EQU     $C401           ;PORT A
-8      DDRB            EQU     $C402           ;DATA DIRECTION
-                                                       REGISTER (A)
-9      DDRA            EQU     $C403           ;DATA DIRECTION
-                                                       REGISTER (B)
-10     *                                       ;ADDRESSES
-                                                       FOR SECOND
-                                                       6522
-11     ORB2            EQU     $C480           ;PORT B
-12     ORA2            EQU     $C481           ;PORT A
-13     DDRB2   EQU     $C482           ;DATA DIRECTION
-                                                       REGISTER (B)
-14     DDRA2   EQU     $C483           ;DATA DIRECTION
-                                                       REGISTER (A)
+                       1       *PRIMARY ROUTINES
+                       2       *FOR SLOT 4
+                       3       *
+                       4                       ORG     $9000
+                       5       *                               ;ADDRESSES
+                                                                               FOR FIRST
+                                                                               6522
+                       6       ORB             EQU     $C400           ;PORT B
+                       7       ORA             EQU     $C401           ;PORT A
+                       8       DDRB            EQU     $C402           ;DATA DIRECTION
+                                                                               REGISTER (A)
+                       9       DDRA            EQU     $C403           ;DATA DIRECTION
+                                                                               REGISTER (B)
+                       10      *                                       ;ADDRESSES
+                                                                               FOR SECOND
+                                                                               6522
+                       11      ORB2            EQU     $C480           ;PORT B
+                       12      ORA2            EQU     $C481           ;PORT A
+                       13      DDRB2   EQU     $C482           ;DATA DIRECTION
+                                                                               REGISTER (B)
+                       14      DDRA2   EQU     $C483           ;DATA DIRECTION
+                                                                               REGISTER (A)
 */
 void WrMem(uint16 addr, uint8 b)
 {
index 56c03d121cb5d481c432fec46d96a6ee8ed4bba6..4f8da2feef95c092a3119ef402b5ac22aba0d2ae 100755 (executable)
 //    freely available as well.
 // 
 
-// JLH: Removed MAME specific crap
+// JLH: Commented out MAME specific crap
 
 #include <string.h>                                                            // for memset()
 #include "ay8910.h"
 
-///////////////////////////////////////////////////////////
-// typedefs & dummy funcs to allow MAME code to compile:
-//
-//typedef UINT8 (*mem_read_handler)(UINT32);
-//typedef void (*mem_write_handler)(UINT32, UINT8);
-//
-//static void logerror(char* psz, ...)
-//{
-//}
-//
-//static unsigned short activecpu_get_pc()
-//{
-//     return 0;
-//}
-//
-//
-///////////////////////////////////////////////////////////
-
-#define MAX_OUTPUT 0x7fff
+#define MAX_OUTPUT 0x7FFF
 
 // See AY8910_set_clock() for definition of STEP
 #define STEP 0x8000
 
-//This is not used at all...
-//static int num = 0, ym_num = 0;
-
 struct AY8910
 {
        int Channel;
@@ -104,60 +83,70 @@ struct AY8910
 static struct AY8910 AYPSG[MAX_8910];          /* array of PSG's */
 
 
-
 void _AYWriteReg(int n, int r, int v)
 {
        struct AY8910 *PSG = &AYPSG[n];
        int old;
 
-
        PSG->Regs[r] = v;
 
-       /* A note about the period of tones, noise and envelope: for speed reasons,*/
-       /* we count down from the period to 0, but careful studies of the chip     */
-       /* output prove that it instead counts up from 0 until the counter becomes */
-       /* greater or equal to the period. This is an important difference when the*/
-       /* program is rapidly changing the period to modulate the sound.           */
-       /* To compensate for the difference, when the period is changed we adjust  */
-       /* our internal counter.                                                   */
-       /* Also, note that period = 0 is the same as period = 1. This is mentioned */
-       /* in the YM2203 data sheets. However, this does NOT apply to the Envelope */
-       /* period. In that case, period = 0 is half as period = 1. */
-       switch( r )
+       /* A note about the period of tones, noise and envelope: for speed reasons, *
+        * we count down from the period to 0, but careful studies of the chip      * 
+        * output prove that it instead counts up from 0 until the counter becomes  * 
+        * greater or equal to the period. This is an important difference when the * 
+        * program is rapidly changing the period to modulate the sound.            * 
+        * To compensate for the difference, when the period is changed we adjust   * 
+        * our internal counter.                                                    * 
+        * Also, note that period = 0 is the same as period = 1. This is mentioned  * 
+        * in the YM2203 data sheets. However, this does NOT apply to the Envelope  * 
+        * period. In that case, period = 0 is half as period = 1.                  */
+       switch (r)
        {
        case AY_AFINE:
        case AY_ACOARSE:
-               PSG->Regs[AY_ACOARSE] &= 0x0f;
+               PSG->Regs[AY_ACOARSE] &= 0x0F;
                old = PSG->PeriodA;
                PSG->PeriodA = (PSG->Regs[AY_AFINE] + 256 * PSG->Regs[AY_ACOARSE]) * PSG->UpdateStep;
+
                if (PSG->PeriodA == 0) PSG->PeriodA = PSG->UpdateStep;
+
                PSG->CountA += PSG->PeriodA - old;
+
                if (PSG->CountA <= 0) PSG->CountA = 1;
                break;
        case AY_BFINE:
        case AY_BCOARSE:
-               PSG->Regs[AY_BCOARSE] &= 0x0f;
+               PSG->Regs[AY_BCOARSE] &= 0x0F;
                old = PSG->PeriodB;
                PSG->PeriodB = (PSG->Regs[AY_BFINE] + 256 * PSG->Regs[AY_BCOARSE]) * PSG->UpdateStep;
+
                if (PSG->PeriodB == 0) PSG->PeriodB = PSG->UpdateStep;
+
                PSG->CountB += PSG->PeriodB - old;
+
                if (PSG->CountB <= 0) PSG->CountB = 1;
                break;
        case AY_CFINE:
        case AY_CCOARSE:
-               PSG->Regs[AY_CCOARSE] &= 0x0f;
+               PSG->Regs[AY_CCOARSE] &= 0x0F;
                old = PSG->PeriodC;
                PSG->PeriodC = (PSG->Regs[AY_CFINE] + 256 * PSG->Regs[AY_CCOARSE]) * PSG->UpdateStep;
+
                if (PSG->PeriodC == 0) PSG->PeriodC = PSG->UpdateStep;
+
                PSG->CountC += PSG->PeriodC - old;
+
                if (PSG->CountC <= 0) PSG->CountC = 1;
                break;
        case AY_NOISEPER:
-               PSG->Regs[AY_NOISEPER] &= 0x1f;
+               PSG->Regs[AY_NOISEPER] &= 0x1F;
                old = PSG->PeriodN;
                PSG->PeriodN = PSG->Regs[AY_NOISEPER] * PSG->UpdateStep;
+
                if (PSG->PeriodN == 0) PSG->PeriodN = PSG->UpdateStep;
+
                PSG->CountN += PSG->PeriodN - old;
+
                if (PSG->CountN <= 0) PSG->CountN = 1;
                break;
        case AY_ENABLE:
@@ -180,17 +169,17 @@ void _AYWriteReg(int n, int r, int v)
                PSG->lastEnable = PSG->Regs[AY_ENABLE];
                break;
        case AY_AVOL:
-               PSG->Regs[AY_AVOL] &= 0x1f;
+               PSG->Regs[AY_AVOL] &= 0x1F;
                PSG->EnvelopeA = PSG->Regs[AY_AVOL] & 0x10;
                PSG->VolA = PSG->EnvelopeA ? PSG->VolE : PSG->VolTable[PSG->Regs[AY_AVOL] ? PSG->Regs[AY_AVOL]*2+1 : 0];
                break;
        case AY_BVOL:
-               PSG->Regs[AY_BVOL] &= 0x1f;
+               PSG->Regs[AY_BVOL] &= 0x1F;
                PSG->EnvelopeB = PSG->Regs[AY_BVOL] & 0x10;
                PSG->VolB = PSG->EnvelopeB ? PSG->VolE : PSG->VolTable[PSG->Regs[AY_BVOL] ? PSG->Regs[AY_BVOL]*2+1 : 0];
                break;
        case AY_CVOL:
-               PSG->Regs[AY_CVOL] &= 0x1f;
+               PSG->Regs[AY_CVOL] &= 0x1F;
                PSG->EnvelopeC = PSG->Regs[AY_CVOL] & 0x10;
                PSG->VolC = PSG->EnvelopeC ? PSG->VolE : PSG->VolTable[PSG->Regs[AY_CVOL] ? PSG->Regs[AY_CVOL]*2+1 : 0];
                break;
@@ -198,8 +187,11 @@ void _AYWriteReg(int n, int r, int v)
        case AY_ECOARSE:
                old = PSG->PeriodE;
                PSG->PeriodE = ((PSG->Regs[AY_EFINE] + 256 * PSG->Regs[AY_ECOARSE])) * PSG->UpdateStep;
+
                if (PSG->PeriodE == 0) PSG->PeriodE = PSG->UpdateStep / 2;
+
                PSG->CountE += PSG->PeriodE - old;
+
                if (PSG->CountE <= 0) PSG->CountE = 1;
                break;
        case AY_ESHAPE:
@@ -229,8 +221,9 @@ void _AYWriteReg(int n, int r, int v)
                has twice the steps, happening twice as fast. Since the end result is
                just a smoother curve, we always use the YM2149 behaviour.
                */
-               PSG->Regs[AY_ESHAPE] &= 0x0f;
-               PSG->Attack = (PSG->Regs[AY_ESHAPE] & 0x04) ? 0x1f : 0x00;
+               PSG->Regs[AY_ESHAPE] &= 0x0F;
+               PSG->Attack = (PSG->Regs[AY_ESHAPE] & 0x04) ? 0x1F : 0x00;
+
                if ((PSG->Regs[AY_ESHAPE] & 0x08) == 0)
                {
                        /* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */
@@ -242,10 +235,12 @@ void _AYWriteReg(int n, int r, int v)
                        PSG->Hold = PSG->Regs[AY_ESHAPE] & 0x01;
                        PSG->Alternate = PSG->Regs[AY_ESHAPE] & 0x02;
                }
+
                PSG->CountE = PSG->PeriodE;
-               PSG->CountEnv = 0x1f;
+               PSG->CountEnv = 0x1F;
                PSG->Holding = 0;
                PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack];
+
                if (PSG->EnvelopeA) PSG->VolA = PSG->VolE;
                if (PSG->EnvelopeB) PSG->VolB = PSG->VolE;
                if (PSG->EnvelopeC) PSG->VolC = PSG->VolE;
@@ -284,76 +279,74 @@ void _AYWriteReg(int n, int r, int v)
 // NB. This should be called at twice the 6522 IRQ rate or (eg) 60Hz if no IRQ.
 void AY8910Update(int chip, int16 ** buffer, int length)       // [TC: Removed static]
 {
-       struct AY8910 *PSG = &AYPSG[chip];
-       INT16 *buf1,*buf2,*buf3;
+       struct AY8910 * PSG = &AYPSG[chip];
+       INT16 * buf1, * buf2, * buf3;
        int outn;
 
        buf1 = buffer[0];
        buf2 = buffer[1];
        buf3 = buffer[2];
 
-
-       /* The 8910 has three outputs, each output is the mix of one of the three */
-       /* tone generators and of the (single) noise generator. The two are mixed */
-       /* BEFORE going into the DAC. The formula to mix each channel is: */
-       /* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */
-       /* Note that this means that if both tone and noise are disabled, the output */
-       /* is 1, not 0, and can be modulated changing the volume. */
-
-
-       /* If the channels are disabled, set their output to 1, and increase the */
-       /* counter, if necessary, so they will not be inverted during this update. */
-       /* Setting the output to 1 is necessary because a disabled channel is locked */
-       /* into the ON state (see above); and it has no effect if the volume is 0. */
-       /* If the volume is 0, increase the counter, but don't touch the output. */
+       /* The 8910 has three outputs, each output is the mix of one of the three    *
+        * tone generators and of the (single) noise generator. The two are mixed    *
+        * BEFORE going into the DAC. The formula to mix each channel is:            *
+        * (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable).                        *
+        * Note that this means that if both tone and noise are disabled, the output *
+        * is 1, not 0, and can be modulated changing the volume.                    *
+        *                                                                           *
+        * If the channels are disabled, set their output to 1, and increase the     *
+        * counter, if necessary, so they will not be inverted during this update.   *
+        * Setting the output to 1 is necessary because a disabled channel is locked *
+        * into the ON state (see above); and it has no effect if the volume is 0.   *
+        * If the volume is 0, increase the counter, but don't touch the output.     */
        if (PSG->Regs[AY_ENABLE] & 0x01)
        {
-               if (PSG->CountA <= length*STEP) PSG->CountA += length*STEP;
+               if (PSG->CountA <= length * STEP) PSG->CountA += length * STEP;
                PSG->OutputA = 1;
        }
        else if (PSG->Regs[AY_AVOL] == 0)
        {
-               /* note that I do count += length, NOT count = length + 1. You might think */
-               /* it's the same since the volume is 0, but doing the latter could cause */
-               /* interferencies when the program is rapidly modulating the volume. */
-               if (PSG->CountA <= length*STEP) PSG->CountA += length*STEP;
+               /* note that I do count += length, NOT count = length + 1. You might think *
+                * it's the same since the volume is 0, but doing the latter could cause   *
+                * interferencies when the program is rapidly modulating the volume.       */
+               if (PSG->CountA <= length * STEP) PSG->CountA += length * STEP;
        }
+
        if (PSG->Regs[AY_ENABLE] & 0x02)
        {
-               if (PSG->CountB <= length*STEP) PSG->CountB += length*STEP;
+               if (PSG->CountB <= length * STEP) PSG->CountB += length * STEP;
                PSG->OutputB = 1;
        }
        else if (PSG->Regs[AY_BVOL] == 0)
        {
-               if (PSG->CountB <= length*STEP) PSG->CountB += length*STEP;
+               if (PSG->CountB <= length * STEP) PSG->CountB += length * STEP;
        }
+
        if (PSG->Regs[AY_ENABLE] & 0x04)
        {
-               if (PSG->CountC <= length*STEP) PSG->CountC += length*STEP;
+               if (PSG->CountC <= length * STEP) PSG->CountC += length * STEP;
                PSG->OutputC = 1;
        }
        else if (PSG->Regs[AY_CVOL] == 0)
        {
-               if (PSG->CountC <= length*STEP) PSG->CountC += length*STEP;
+               if (PSG->CountC <= length * STEP) PSG->CountC += length * STEP;
        }
 
-       /* for the noise channel we must not touch OutputN - it's also not necessary */
-       /* since we use outn. */
+       /* for the noise channel we must not touch OutputN - it's also not necessary *
+        * since we use outn.                                                        */
        if ((PSG->Regs[AY_ENABLE] & 0x38) == 0x38)      /* all off */
-               if (PSG->CountN <= length*STEP) PSG->CountN += length*STEP;
+               if (PSG->CountN <= length * STEP) PSG->CountN += length * STEP;
 
        outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);
 
-
        /* buffering loop */
        while (length)
        {
-               int vola,volb,volc;
+               int vola, volb, volc;
                int left;
 
-
-               /* vola, volb and volc keep track of how long each square wave stays */
-               /* in the 1 position during the sample period. */
+               /* vola, volb and volc keep track of how long each square wave stays *
+                * in the 1 position during the sample period.                       */
                vola = volb = volc = 0;
 
                left = STEP;
@@ -361,34 +354,38 @@ void AY8910Update(int chip, int16 ** buffer, int length)  // [TC: Removed static]
                {
                        int nextevent;
 
-
                        if (PSG->CountN < left) nextevent = PSG->CountN;
                        else nextevent = left;
 
                        if (outn & 0x08)
                        {
                                if (PSG->OutputA) vola += PSG->CountA;
+
                                PSG->CountA -= nextevent;
-                               /* PeriodA is the half period of the square wave. Here, in each */
-                               /* loop I add PeriodA twice, so that at the end of the loop the */
-                               /* square wave is in the same status (0 or 1) it was at the start. */
-                               /* vola is also incremented by PeriodA, since the wave has been 1 */
-                               /* exactly half of the time, regardless of the initial position. */
-                               /* If we exit the loop in the middle, OutputA has to be inverted */
-                               /* and vola incremented only if the exit status of the square */
-                               /* wave is 1. */
+                               /* PeriodA is the half period of the square wave. Here, in each    *
+                                * loop I add PeriodA twice, so that at the end of the loop the    *
+                                * square wave is in the same status (0 or 1) it was at the start. *
+                                * vola is also incremented by PeriodA, since the wave has been 1  *
+                                * exactly half of the time, regardless of the initial position.   *
+                                * If we exit the loop in the middle, OutputA has to be inverted   *
+                                * and vola incremented only if the exit status of the square      *
+                                * wave is 1.                                                      */
                                while (PSG->CountA <= 0)
                                {
                                        PSG->CountA += PSG->PeriodA;
+
                                        if (PSG->CountA > 0)
                                        {
                                                PSG->OutputA ^= 1;
+
                                                if (PSG->OutputA) vola += PSG->PeriodA;
                                                break;
                                        }
+
                                        PSG->CountA += PSG->PeriodA;
                                        vola += PSG->PeriodA;
                                }
+
                                if (PSG->OutputA) vola -= PSG->CountA;
                        }
                        else
@@ -397,11 +394,13 @@ void AY8910Update(int chip, int16 ** buffer, int length)  // [TC: Removed static]
                                while (PSG->CountA <= 0)
                                {
                                        PSG->CountA += PSG->PeriodA;
+
                                        if (PSG->CountA > 0)
                                        {
                                                PSG->OutputA ^= 1;
                                                break;
                                        }
+
                                        PSG->CountA += PSG->PeriodA;
                                }
                        }
@@ -409,32 +408,41 @@ void AY8910Update(int chip, int16 ** buffer, int length)  // [TC: Removed static]
                        if (outn & 0x10)
                        {
                                if (PSG->OutputB) volb += PSG->CountB;
+
                                PSG->CountB -= nextevent;
+
                                while (PSG->CountB <= 0)
                                {
                                        PSG->CountB += PSG->PeriodB;
+
                                        if (PSG->CountB > 0)
                                        {
                                                PSG->OutputB ^= 1;
+
                                                if (PSG->OutputB) volb += PSG->PeriodB;
                                                break;
                                        }
+
                                        PSG->CountB += PSG->PeriodB;
                                        volb += PSG->PeriodB;
                                }
+
                                if (PSG->OutputB) volb -= PSG->CountB;
                        }
                        else
                        {
                                PSG->CountB -= nextevent;
+
                                while (PSG->CountB <= 0)
                                {
                                        PSG->CountB += PSG->PeriodB;
+
                                        if (PSG->CountB > 0)
                                        {
                                                PSG->OutputB ^= 1;
                                                break;
                                        }
+
                                        PSG->CountB += PSG->PeriodB;
                                }
                        }
@@ -442,74 +450,90 @@ void AY8910Update(int chip, int16 ** buffer, int length)  // [TC: Removed static]
                        if (outn & 0x20)
                        {
                                if (PSG->OutputC) volc += PSG->CountC;
+
                                PSG->CountC -= nextevent;
+
                                while (PSG->CountC <= 0)
                                {
                                        PSG->CountC += PSG->PeriodC;
+
                                        if (PSG->CountC > 0)
                                        {
                                                PSG->OutputC ^= 1;
+
                                                if (PSG->OutputC) volc += PSG->PeriodC;
                                                break;
                                        }
+
                                        PSG->CountC += PSG->PeriodC;
                                        volc += PSG->PeriodC;
                                }
+
                                if (PSG->OutputC) volc -= PSG->CountC;
                        }
                        else
                        {
                                PSG->CountC -= nextevent;
+
                                while (PSG->CountC <= 0)
                                {
                                        PSG->CountC += PSG->PeriodC;
+
                                        if (PSG->CountC > 0)
                                        {
                                                PSG->OutputC ^= 1;
                                                break;
                                        }
+
                                        PSG->CountC += PSG->PeriodC;
                                }
                        }
 
                        PSG->CountN -= nextevent;
+
                        if (PSG->CountN <= 0)
                        {
                                /* Is noise output going to change? */
-                               if ((PSG->RNG + 1) & 2) /* (bit0^bit1)? */
+                               if ((PSG->RNG + 1) & 0x00002)   /* (bit0^bit1)? */
                                {
                                        PSG->OutputN = ~PSG->OutputN;
                                        outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);
                                }
 
-                               /* The Random Number Generator of the 8910 is a 17-bit shift */
-                               /* register. The input to the shift register is bit0 XOR bit3 */
-                               /* (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. */
+                               /* The Random Number Generator of the 8910 is a 17-bit shift  *
+                                * register. The input to the shift register is bit0 XOR bit3 *
+                                * (bit0 is the output). This was verified on AY-3-8910 and   *
+                                * YM2149 chips.                                              *
+                                *                                                            *
+                                * The following is a fast way to compute bit17 = bit0^bit3.  *
+                                * Instead of doing all the logic operations, we only check   *
+                                * bit0, relying on the fact that after three shifts of the   *
+                                * register, what now is bit3 will become bit0, and will      *
+                                * invert, if necessary, bit14, which previously was bit17.   */
+                               if (PSG->RNG & 0x00001)
+                                       PSG->RNG ^= 0x24000; /* This version is called the "Galois configuration". */
 
-                               /* The following is a fast way to compute bit17 = bit0^bit3. */
-                               /* Instead of doing all the logic operations, we only check */
-                               /* bit0, relying on the fact that after three shifts of the */
-                               /* register, what now is bit3 will become bit0, and will */
-                               /* invert, if necessary, bit14, which previously was bit17. */
-                               if (PSG->RNG & 1) PSG->RNG ^= 0x24000; /* This version is called the "Galois configuration". */
                                PSG->RNG >>= 1;
                                PSG->CountN += PSG->PeriodN;
                        }
 
                        left -= nextevent;
-               } while (left > 0);
+               }
+               while (left > 0);
 
                /* update envelope */
                if (PSG->Holding == 0)
                {
                        PSG->CountE -= STEP;
+
                        if (PSG->CountE <= 0)
                        {
                                do
                                {
                                        PSG->CountEnv--;
                                        PSG->CountE += PSG->PeriodE;
-                               } while (PSG->CountE <= 0);
+                               }
+                               while (PSG->CountE <= 0);
 
                                /* check envelope current position */
                                if (PSG->CountEnv < 0)
@@ -517,18 +541,19 @@ void AY8910Update(int chip, int16 ** buffer, int length)  // [TC: Removed static]
                                        if (PSG->Hold)
                                        {
                                                if (PSG->Alternate)
-                                                       PSG->Attack ^= 0x1f;
+                                                       PSG->Attack ^= 0x1F;
+
                                                PSG->Holding = 1;
                                                PSG->CountEnv = 0;
                                        }
                                        else
                                        {
-                                               /* if CountEnv has looped an odd number of times (usually 1), */
-                                               /* invert the output. */
+                                               /* if CountEnv has looped an odd number of times (usually 1), *
+                                                * invert the output.                                         */
                                                if (PSG->Alternate && (PSG->CountEnv & 0x20))
-                                                       PSG->Attack ^= 0x1f;
+                                                       PSG->Attack ^= 0x1F;
 
-                                               PSG->CountEnv &= 0x1f;
+                                               PSG->CountEnv &= 0x1F;
                                        }
                                }
 
@@ -544,90 +569,77 @@ void AY8910Update(int chip, int16 ** buffer, int length)  // [TC: Removed static]
                *(buf1++) = (vola * PSG->VolA) / STEP;
                *(buf2++) = (volb * PSG->VolB) / STEP;
                *(buf3++) = (volc * PSG->VolC) / STEP;
-#else
+#else  // [Tom's code...]
                // Output PCM wave [-32768...32767] instead of MAME's voltage level [0...32767]
                // - This allows for better s/w mixing
 
-               if(PSG->VolA)
+               if (PSG->VolA)
                {
-                       if(vola)
+                       if (vola)
                                *(buf1++) = (vola * PSG->VolA) / STEP;
                        else
-                               *(buf1++) = - (int) PSG->VolA;
+                               *(buf1++) = -(int)PSG->VolA;
                }
                else
-               {
                        *(buf1++) = 0;
-               }
 
-               //
-
-               if(PSG->VolB)
+               if (PSG->VolB)
                {
-                       if(volb)
+                       if (volb)
                                *(buf2++) = (volb * PSG->VolB) / STEP;
                        else
-                               *(buf2++) = - (int) PSG->VolB;
+                               *(buf2++) = -(int)PSG->VolB;
                }
                else
-               {
                        *(buf2++) = 0;
-               }
 
-               //
-
-               if(PSG->VolC)
+               if (PSG->VolC)
                {
-                       if(volc)
+                       if (volc)
                                *(buf3++) = (volc * PSG->VolC) / STEP;
                        else
-                               *(buf3++) = - (int) PSG->VolC;
+                               *(buf3++) = -(int)PSG->VolC;
                }
                else
-               {
                        *(buf3++) = 0;
-               }
 #endif
-
                length--;
        }
 }
 
 
-static void AY8910_set_clock(int chip,int clock)
+static void AY8910_set_clock(int chip, int clock)
 {
-       struct AY8910 *PSG = &AYPSG[chip];
-
-       /* the step clock for the tone and noise generators is the chip clock    */
-       /* divided by 8; for the envelope generator of the AY-3-8910, it is half */
-       /* that much (clock/16), but the envelope of the YM2149 goes twice as    */
-       /* fast, therefore again clock/8.                                        */
-       /* Here we calculate the number of steps which happen during one sample  */
-       /* at the given sample rate. No. of events = sample rate / (clock/8).    */
-       /* STEP is a multiplier used to turn the fraction into a fixed point     */
-       /* number.                                                               */
-       PSG->UpdateStep = (unsigned int) (((double)STEP * PSG->SampleRate * 8 + clock/2) / clock);      // [TC: unsigned int cast]
+       struct AY8910 * PSG = &AYPSG[chip];
+
+       /* The step clock for the tone and noise generators is the chip clock    *
+        * divided by 8; for the envelope generator of the AY-3-8910, it is half *
+        * that much (clock/16), but the envelope of the YM2149 goes twice as    *
+        * fast, therefore again clock/8.                                        *
+        * Here we calculate the number of steps which happen during one sample  *
+        * at the given sample rate. No. of events = sample rate / (clock/8).    *
+        * STEP is a multiplier used to turn the fraction into a fixed point     *
+        * number.                                                               */
+       PSG->UpdateStep = (unsigned int)(((double)STEP * PSG->SampleRate * 8 + clock / 2) / clock);     // [TC: unsigned int cast]
 }
 
 
 static void build_mixer_table(int chip)
 {
-       struct AY8910 *PSG = &AYPSG[chip];
-       int i;
-       double out;
+       struct AY8910 * PSG = &AYPSG[chip];
 
-
-       /* calculate the volume->voltage conversion table */
+       /* calculate the volume->voltage conversion table                     */
        /* The AY-3-8910 has 16 levels, in a logarithmic scale (3dB per step) */
        /* The YM2149 still has 16 levels for the tone generators, but 32 for */
-       /* the envelope generator (1.5dB per step). */
-       out = MAX_OUTPUT;
-       for (i = 31;i > 0;i--)
-       {
-               PSG->VolTable[i] = (unsigned int) (out + 0.5);  /* round to nearest */  // [TC: unsigned int cast]
+       /* the envelope generator (1.5dB per step).                           */
+       double out = MAX_OUTPUT;
 
+       for(int i=31; i>0; i--)
+       {
+               PSG->VolTable[i] = (unsigned int)(out + 0.5);   /* round to nearest */  // [TC: unsigned int cast]
                out /= 1.188502227;     /* = 10 ^ (1.5/20) = 1.5dB */
        }
+
        PSG->VolTable[0] = 0;
 }
 
@@ -635,59 +647,48 @@ static void build_mixer_table(int chip)
 void AY8910_reset(int chip)
 {
        int i;
-       struct AY8910 *PSG = &AYPSG[chip];
+       struct AY8910 * PSG = &AYPSG[chip];
 
        PSG->register_latch = 0;
        PSG->RNG = 1;
        PSG->OutputA = 0;
        PSG->OutputB = 0;
        PSG->OutputC = 0;
-       PSG->OutputN = 0xff;
+       PSG->OutputN = 0xFF;
        PSG->lastEnable = -1;   /* force a write */
-       for (i = 0;i < AY_PORTA;i++)
-               _AYWriteReg(chip,i,0);  /* AYWriteReg() uses the timer system; we cannot */
-                                                               /* call it at this time because the timer system */
-                                                               /* has not been initialized. */
+
+       for(i=0; i<AY_PORTA; i++)
+               _AYWriteReg(chip, i, 0);        /* AYWriteReg() uses the timer system; we cannot */
+                                                                       /* call it at this time because the timer system */
+                                                                       /* has not been initialized.                     */
 }
 
-//-------------------------------------
+// This stuff looks like Tom's code, so let's streamline and un-MSHungarianize this shit:
+// [DONE]
 
-void AY8910_InitAll(int nClock, int nSampleRate)
+void AY8910_InitAll(int clock, int sampleRate)
 {
-       for(int nChip=0; nChip<MAX_8910; nChip++)
+       for(int chip=0; chip<MAX_8910; chip++)
        {
-               struct AY8910 *PSG = &AYPSG[nChip];
-
-               memset(PSG,0,sizeof(struct AY8910));
-               PSG->SampleRate = nSampleRate;
-
-//             PSG->PortAread = NULL;
-//             PSG->PortBread = NULL;
-//             PSG->PortAwrite = NULL;
-//             PSG->PortBwrite = NULL;
+               struct AY8910 * PSG = &AYPSG[chip];
 
-               AY8910_set_clock(nChip, nClock);
-
-               build_mixer_table(nChip);
+               memset(PSG, 0, sizeof(struct AY8910));
+               PSG->SampleRate = sampleRate;
+               AY8910_set_clock(chip, clock);
+               build_mixer_table(chip);
        }
 }
 
-//-------------------------------------
-
-void AY8910_InitClock(int nClock)
+void AY8910_InitClock(int clock)
 {
-       for(int nChip=0; nChip<MAX_8910; nChip++)
-       {
-               AY8910_set_clock(nChip, nClock);
-       }
+       for(int chip=0; chip<MAX_8910; chip++)
+               AY8910_set_clock(chip, clock);
 }
 
-//-------------------------------------
-
-uint8 * AY8910_GetRegsPtr(uint16 nAyNum)
+uint8 * AY8910_GetRegsPtr(uint16 chipNum)
 {
-       if(nAyNum >= MAX_8910)
+       if (chipNum >= MAX_8910)
                return NULL;
 
-       return &AYPSG[nAyNum].Regs[0];
+       return &AYPSG[chipNum].Regs[0];
 }
index 4c4119f7b9be6f0e41e53ef1dfcbb966103b6771..b5af684a92c9e1d0492116f514fc5568c1fc7bec 100755 (executable)
@@ -26,8 +26,6 @@
 #define MASK_A 0xFF000000
 #endif
 
-using namespace std;                                                           // For STL stuff
-
 //
 // Button class implementation
 //
@@ -35,7 +33,7 @@ using namespace std;                                                          // For STL stuff
 /*
 Some notes about this class:
 
-- Button colors are hardwired
+- Button colors are hardwired (for plain text buttons)
 */
 
 Button::Button(uint32 x/*= 0*/, uint32 y/*= 0*/, uint32 w/*= 0*/, uint32 h/*= 0*/,
@@ -78,7 +76,7 @@ Button::Button(uint32 x, uint32 y, SDL_Surface * bU, SDL_Surface * bH/*= NULL*/,
                extents.h = buttonUp->h;
 }
 
-Button::Button(uint32 x, uint32 y, uint32 w, uint32 h, string s, Element * parent/*= NULL*/):
+Button::Button(uint32 x, uint32 y, uint32 w, uint32 h, std::string s, Element * parent/*= NULL*/):
        Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
        activated(false), clicked(false), inside(false),
        buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(true),
@@ -87,7 +85,7 @@ Button::Button(uint32 x, uint32 y, uint32 w, uint32 h, string s, Element * paren
        // Create the button surfaces here...
 }
 
-Button::Button(uint32 x, uint32 y, string s, Element * parent/*= NULL*/):
+Button::Button(uint32 x, uint32 y, std::string s, Element * parent/*= NULL*/):
        Element(x, y, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
        activated(false), clicked(false), inside(false),
        buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(true),
@@ -170,8 +168,6 @@ void Button::Draw(void)
        if (buttonUp == NULL)
                return;                                                                 // Bail out if no surface was created...
 
-       SDL_Rect rect = GetScreenCoords();
-
        // Now, draw the appropriate button state!
 
        SDL_Surface * picToShow = buttonUp;
@@ -182,6 +178,10 @@ void Button::Draw(void)
        if (buttonDown != NULL && inside && clicked)
                picToShow = buttonDown;
 
+       SDL_Rect rect = GetScreenCoords();
+
+//Need to do coverage list blitting here, to avoid unnecessary drawing when doing mouseovers
+//Also, need to add suport in Gui()...
        SDL_BlitSurface(picToShow, NULL, screen, &rect);        // This handles alpha blending too! :-D
 
        needToRefreshScreen = true;
index fcf366bbc8ad205d2700bff0368d521738609d45..8009486f0bf6c0c75460f04de218542df32ba91a 100755 (executable)
@@ -8,6 +8,7 @@
 #define __BUTTON_H__
 
 #include <string>
+//#include <list>
 #include "element.h"
 
 //Apparently this approach doesn't work for inheritance... D'oh!
index 860e35d4fc2e8bf5f21443d2601f123608065377..45635bff2dc77f4e79a70800a2459159ee64caa8 100755 (executable)
@@ -32,9 +32,8 @@
 #define MASK_A 0xFF000000
 #endif
 
-using namespace std;                                                           // For STL stuff
-
 #define BACKGROUND_IMG_TEST
+//#define USE_COVERAGE_LISTS
 
 //
 // DraggableWindow class implementation
@@ -142,6 +141,16 @@ void DraggableWindow::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
 
 void DraggableWindow::Draw(void)
 {
+#ifdef USE_COVERAGE_LISTS
+       // These are *always* top level and parentless, so no need to traverse up through
+       // the parent chain...
+       for(std::list<SDL_Rect>::iterator i=coverList.begin(); i!=coverList.end(); i++)
+               SDL_FillRect(screen, &(*i), bgColor);
+
+       // Handle the items this window contains...
+       for(uint32 i=0; i<list.size(); i++)
+               list[i]->Draw();
+#else
        // These are *always* top level and parentless, so no need to traverse up through
        // the parent chain...
 //Perhaps we can make these parentable, put the parent traversal in the base class?
@@ -167,6 +176,7 @@ void DraggableWindow::Draw(void)
        // Handle the items this window contains...
        for(uint32 i=0; i<list.size(); i++)
                list[i]->Draw();
+#endif
 
 //Prolly don't need this since the close button will do this for us...
        needToRefreshScreen = true;
index dc73bb9fd33e6592b349eef82fac9add22b52c1a..bbaff3cc757598c1e826b7c1387013b16667a1c0 100755 (executable)
@@ -15,6 +15,7 @@
 //
 
 #include "element.h"
+#include "guimisc.h"                                                           // Various support functions
 
 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
 #define MASK_R 0xFF000000
@@ -46,6 +47,7 @@ Element::Element(uint32 x/*= 0*/, uint32 y/*= 0*/, uint32 w/*= 0*/, uint32 h/*=
        extents.y = y,
        extents.w = w,
        extents.h = h;
+       coverList.push_back(extents);
 }
 
 Element::Element(uint32 x, uint32 y, uint32 w, uint32 h,
@@ -57,6 +59,7 @@ Element::Element(uint32 x, uint32 y, uint32 w, uint32 h,
        extents.y = y,
        extents.w = w,
        extents.h = h;
+       coverList.push_back(extents);
 
        // This *should* allow us to store our colors in an endian safe way... :-/
        uint8 * c = (uint8 *)&fgColor;
@@ -81,7 +84,7 @@ bool Element::Inside(uint32 x, uint32 y)
                && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false);
 }
 
-//Badly named--!!! FIX !!!
+//Badly named--!!! FIX !!! [DONE]
 //SDL_Rect Element::GetParentCorner(void)
 SDL_Rect Element::GetScreenCoords(void)
 {
@@ -102,7 +105,7 @@ SDL_Rect Element::GetScreenCoords(void)
        return rect;
 }
 
-#if 0
+#if 1
 //May use this in the future...
 SDL_Rect Element::GetParentRect(void)
 {
@@ -124,6 +127,11 @@ SDL_Rect Element::GetParentRect(void)
 }
 #endif
 
+SDL_Rect Element::GetExtents(void)
+{
+       return extents;
+}
+
 void Element::CreateBackstore(void)
 {
        backstore = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
@@ -140,6 +148,145 @@ void Element::RestoreScreenFromBackstore(void)
        SDL_BlitSurface(backstore, NULL, screen, &r);
 }
 
+void Element::SaveScreenToBackstore(void)
+{
+       SDL_BlitSurface(screen, &extents, backstore, NULL);
+}
+
+void Element::ResetCoverageList(void)
+{
+       // Setup our coverage list with the entire window area
+       coverList.empty();
+       coverList.push_back(extents);
+}
+
+void Element::AdjustCoverageList(SDL_Rect r)
+{
+//Prolly should have a bool here to set whether or not to do this crap, since it
+//takes a little time...
+
+       // Here's where we do the coverage list voodoo... :-)
+
+/*
+Steps:
+  o Check for intersection. If no intersection, then no need to divide rects.
+  o Loop through current rects. If rect is completely inside passed in rect, remove from list.
+  o Loop through remaining rects. If rect intersects, decompose to four rects and
+    exclude degenerate rects, push rest into the coverage list.
+
+*/
+//     std::list<Element *>::reverse_iterator ri;
+//     std::list<SDL_Rect>::iterator i;
+
+       // Loop through rects and remove those completely covered by passed in rect.
+/*     for(i=coverList.begin(); i!=coverList.end(); i++)
+       {
+//             if (RectanglesIntersect(r, *i))
+               if (RectangleFirstInsideSecond(*i, r))
+               {
+//This is not right--do a while loop instead of a for loop?
+                       // Remove it from the list...
+                       std::list<SDL_Rect>::iterator next = coverList.erase(i);
+               }
+       }
+*/
+       // Loop through rects and remove those completely covered by passed in rect.
+       std::list<SDL_Rect>::iterator i = coverList.begin();
+
+       while (i != coverList.end())
+       {
+               if (RectangleFirstInsideSecond(*i, r))
+                       i = coverList.erase(i);                         // This will also advance i to the next item!
+               else
+                       i++;
+       }
+
+//This may not be needed if nothing follows the loop below...!
+//     if (coverList.empty())
+//             return;
+
+       // Check for intersection. If no intersection, then no need to divide rects.
+       i = coverList.begin();
+
+       while (i != coverList.end())
+       {
+               if (RectanglesIntersect(r, *i))
+               {
+                       // Do the decomposition here. There will always be at least *one* rectangle
+                       // generated by this algorithm, so we know we're OK in removing the original
+                       // from the list. The general pattern looks like this:
+                       //
+                       // +------+
+                       // |1     |
+                       // +-+--+-+
+                       // |2|//|3|  <- Rectangle "r" is in the center
+                       // +-+--+-+
+                       // |4     |
+                       // +------+
+                       //
+                       // Even if r extends beyond the bounds of the rectangle under consideration,
+                       // that's OK because we test to see that the rectangle isn't degenerate
+                       // before adding it to the list.
+
+//Should probably use a separate list here and splice it in when we're done here...
+//Or, could use push_front() to avoid the problem... Neat! Doesn't require a separate list!
+//But, we need to remove the currently referenced rect... Another while loop!
+
+//This approach won't work--if no rect1 then we're screwed! [FIXED]
+//Now *that* will work...
+                       SDL_Rect current = *i;
+                       uint32 bottomOfRect1 = current.y;
+//                     uint32 rightOfRect2 = current.x;
+//                     uint32 leftOfRect3 = current.x + current.w;
+                       uint32 topOfRect4 = current.y + current.h;
+
+                       // Rectangle #1 (top)
+                       if (r.y > current.y)                            // Simple rectangle degeneracy test...
+                       {
+                               bottomOfRect1 = r.y;
+                               SDL_Rect rect = current;
+                               rect.h = r.y - current.y;
+                               coverList.push_front(rect);
+                       }
+
+                       // Rectangle #4 (bottom)
+                       if (r.y + r.h < current.y + current.h)
+                       {
+                               topOfRect4 = r.y + r.h;
+                               SDL_Rect rect = current;
+                               rect.y = r.y + r.h;
+                               rect.h = (current.y + current.h) - (r.y + r.h);
+                               coverList.push_front(rect);
+                       }
+
+                       // Rectangle #2 (left side)
+                       if (r.x > current.x)
+                       {
+                               SDL_Rect rect = current;
+                               rect.w = r.x - current.x;
+                               rect.y = bottomOfRect1;
+                               rect.h = topOfRect4 - bottomOfRect1;
+                               coverList.push_front(rect);
+                       }
+
+                       // Rectangle #3 (right side)
+                       if (r.x + r.w < current.x + current.w)
+                       {
+                               SDL_Rect rect;
+                               rect.x = r.x + r.w;
+                               rect.w = (current.x + current.w) - (r.x + r.w);
+                               rect.y = bottomOfRect1;
+                               rect.h = topOfRect4 - bottomOfRect1;
+                               coverList.push_front(rect);
+                       }
+
+                       i = coverList.erase(i);                         // This will also advance i to the next item!
+               }
+               else
+                       i++;
+       }
+}
+
 //
 // Class methods
 //
index a53d0011d7b85584792171eec856ee7068529291..a090a968c2164b9f92f1f912268d171cc3210c41 100755 (executable)
@@ -13,6 +13,7 @@
 enum { WINDOW_CLOSE, MENU_ITEM_CHOSEN, SCREEN_REFRESH_NEEDED };
 
 #include <SDL.h>
+#include <list>
 #include "types.h"
 
 class Element
@@ -34,12 +35,17 @@ class Element
 //Badly named, though we may code something that does this...
 //             SDL_Rect GetParentCorner(void);
                SDL_Rect GetScreenCoords(void);
-#if 0
+               SDL_Rect GetExtents(void);
+#if 1
 //May use this in the future...
                SDL_Rect GetParentRect(void);
 #endif
                void CreateBackstore(void);
                void RestoreScreenFromBackstore(void);
+               void SaveScreenToBackstore(void);
+               void ResetCoverageList(void);
+//Need something to prevent this on Elements that don't have mouseover effects...
+               void AdjustCoverageList(SDL_Rect r);
                // Class methods...
                static void SetScreen(SDL_Surface *);
                static bool ScreenNeedsRefreshing(void);
@@ -52,6 +58,7 @@ class Element
                uint32 fgColor;
                uint32 bgColor;
                SDL_Surface * backstore;
+               std::list<SDL_Rect> coverList;
 
                // Class variables...
                static SDL_Surface * screen;
index ef5ef97b507417337094fcdffee16fc375e3c262..2841992fc2ba07e8ddf2ab7cff55d1ee9f996067 100755 (executable)
 // ---  ----------  ------------------------------------------------------------
 // JLH  02/03/2006  Created this file
 // JLH  03/13/2006  Added functions to allow shutting down GUI externally
+// JLH  03/22/2006  Finalized basic multiple window support
 //
-
-// STILL TO FIX:
+// STILL TO DO:
 //
-// - Memory leak on quitting with a window active
-// - Multiple window handling
+// - Memory leak on quitting with a window active [DONE]
+// - Multiple window handling [DONE]
 //
 
 #include "gui.h"
 
 //#define DEBUG_MAIN_LOOP
 
-#ifdef DEBUG_MAIN_LOOP
+//#ifdef DEBUG_MAIN_LOOP
 #include "log.h"
-#endif
+//#endif
 
 
-GUI::GUI(SDL_Surface * mainSurface): mainMenu(new Menu()), menuItem(new MenuItems())
+GUI::GUI(SDL_Surface * mainSurface): menuItem(new MenuItems())
 {
+       windowList.push_back(new Menu());
        Element::SetScreen(mainSurface);
 }
 
 GUI::~GUI()
 {
-       if (mainMenu)
-               delete mainMenu;
+       // Clean up menuItem, if any
 
        if (menuItem)
                delete menuItem;
+
+       // Clean up the rest
+
+       for(std::list<Element *>::iterator i=windowList.begin(); i!=windowList.end(); i++)
+               if (*i)
+                       delete *i;
 }
 
 void GUI::AddMenuTitle(const char * title)
@@ -59,25 +65,32 @@ void GUI::AddMenuItem(const char * item, Element * (* a)(void)/*= NULL*/, SDLKey
 
 void GUI::CommitItemsToMenu(void)
 {
-       mainMenu->Add(*menuItem);
-}
+//We could just do a simple check here to see if more than one item is in the list,
+//and if so fail. Make it so you build the menu first before allowing any other action. [DONE]
+
+//Right now, we just silently fail...
+       if (windowList.size() > 1)
+       {
+               WriteLog("GUI: Can't find menu--more than one item in windowList!\n");
+               return;
+       }
 
+       ((Menu *)(*windowList.begin()))->Add(*menuItem);
+}
 
 void GUI::Run(void)
 {
        exitGUI = false;
-
-       bool showMouse = true;
-       int mouseX = 0, mouseY = 0;
-       int oldMouseX = 0, oldMouseY = 0;
-       Element * mainWindow = NULL;
+       showMouse = true;
        SDL_Event event;
+       std::list<Element *>::iterator i;
 
        SDL_EnableKeyRepeat(150, 75);
-       // Initial update...
-//Shouldn't we save the state of the GUI instead of doing things this way?
-//We have a memory leak whenever a mainWindow is active and we quit... !!! FIX !!!
-       mainMenu->Draw();
+
+       // Initial update... [Now handled correctly in the constructor]
+       for(i=windowList.begin(); i!=windowList.end(); i++)
+               (*i)->Draw();
+
        RenderScreenBuffer();
 
        // Main loop
@@ -96,35 +109,47 @@ WriteLog(" -- SDL_USEREVENT\n");
 //Mebbe add another user event for screen refresh? Why not!
                                if (event.user.code == WINDOW_CLOSE)
                                {
-                                       delete mainWindow;
-                                       mainWindow = NULL;
+                                       for(i=windowList.begin(); i!=windowList.end(); i++)
+                                       {
+                                               if (*i == (Element *)event.user.data1)
+                                               {
+                                                       delete *i;
+                                                       windowList.erase(i);
+                                                       break;
+                                               }
+                                       }
                                }
                                else if (event.user.code == MENU_ITEM_CHOSEN)
                                {
                                        // Confused? Let me enlighten... What we're doing here is casting
-                                       // data1 as a pointer to a function which returns a Window pointer and
-                                       // which takes no parameters (the "(Window *(*)(void))" part), then
+                                       // data1 as a pointer to a function which returns a Element pointer and
+                                       // which takes no parameters (the "(Element *(*)(void))" part), then
                                        // derefencing it (the "*" in front of that) in order to call the
                                        // function that it points to. Clear as mud? Yeah, I hate function
                                        // pointers too, but what else are you gonna do?
-                                       mainWindow = (*(Element *(*)(void))event.user.data1)();
+                                       Element * window = (*(Element *(*)(void))event.user.data1)();
+
+                                       if (window)
+                                               windowList.push_back(window);
 
                                        while (SDL_PollEvent(&event));  // Flush the event queue...
+
                                        event.type = SDL_MOUSEMOTION;
                                        int mx, my;
                                        SDL_GetMouseState(&mx, &my);
                                        event.motion.x = mx, event.motion.y = my;
                                    SDL_PushEvent(&event);                      // & update mouse position...!
 
-                                       oldMouseX = mouseX, oldMouseY = mouseY;
-                                       mouseX = mx, mouseY = my;               // This prevents "mouse flash"...
+                                       oldMouse.x = mouse.x, oldMouse.y = mouse.y;
+                                       mouse.x = mx, mouse.y = my;             // This prevents "mouse flash"...
                                }
-//There's a *small* problem with this approach--if a window and a bunch of child
-//widgets send this message, we'll get a bunch of unnecessary refresh events...
+//There's a *small* problem with the following approach--if a window and a bunch of
+//child widgets send this message, we'll get a bunch of unnecessary refresh events...
 //This could be controlled by having the main window refresh itself intelligently...
 
 //What we could do instead is set a variable in Element and check it after the fact
 //to see whether or not a refresh is needed.
+//[This is what we do now.]
 
 //Dirty rectangle is also possible...
                                else if (event.user.code == SCREEN_REFRESH_NEEDED)
@@ -132,58 +157,235 @@ WriteLog(" -- SDL_USEREVENT\n");
                        }
                        else if (event.type == SDL_ACTIVEEVENT)
                        {
+//Need to do a screen refresh here...
                                if (event.active.state == SDL_APPMOUSEFOCUS)
                                        showMouse = (event.active.gain ? true : false);
+
+                               RenderScreenBuffer();
                        }
                        else if (event.type == SDL_KEYDOWN)
                        {
 #ifdef DEBUG_MAIN_LOOP
 WriteLog(" -- SDL_KEYDOWN\n");
 #endif
-                               if (event.key.keysym.sym == SDLK_F5)
+                               if (event.key.keysym.sym == SDLK_F1)
                                        exitGUI = true;
 
-                               if (mainWindow)
-                                       mainWindow->HandleKey(event.key.keysym.sym);
-                               else
-                                       mainMenu->HandleKey(event.key.keysym.sym);
+//Not sure that this is the right way to handle this...
+//Probably should only give this to the top level window...
+//                             for(i=windowList.begin(); i!=windowList.end(); i++)
+//                                     (*i)->HandleKey(event.key.keysym.sym);
+                               windowList.back()->HandleKey(event.key.keysym.sym);
                        }
                        else if (event.type == SDL_MOUSEMOTION)
                        {
 #ifdef DEBUG_MAIN_LOOP
 WriteLog(" -- SDL_MOUSEMOTION\n");
 #endif
-                               oldMouseX = mouseX, oldMouseY = mouseY;
-                               mouseX = event.motion.x, mouseY = event.motion.y;
+//This is for tracking a custom mouse cursor, which we're not doing--YET.
+                               oldMouse.x = mouse.x, oldMouse.y = mouse.y;
+                               mouse.x = event.motion.x, mouse.y = event.motion.y;
 
-                               if (mainWindow)
-                                       mainWindow->HandleMouseMove(mouseX, mouseY);
-                               else
-                                       mainMenu->HandleMouseMove(mouseX, mouseY);
+//Not sure that this is the right way to handle this...
+//Right now, we should probably only do mouseover for the last item in the list...
+//And now we do!
+//Though, it seems to screw other things up. Maybe it IS better to pass it to all windows?
+//Or maybe to just the ones that aren't completely obscured?
+//Probably. Right now, a disk's close button that should be obscured by one sitting on
+//top of it gets redrawn. Not good.
+                               for(i=windowList.begin(); i!=windowList.end(); i++)
+                                       (*i)->HandleMouseMove(mouse.x, mouse.y);
+//                             windowList.back()->HandleMouseMove(mouse.x, mouse.y);
                        }
                        else if (event.type == SDL_MOUSEBUTTONDOWN)
                        {
 #ifdef DEBUG_MAIN_LOOP
-WriteLog(" -- SDL_MOSEBUTTONDOWN\n");
+WriteLog(" -- SDL_MOUSEBUTTONDOWN\n");
 #endif
-                               uint32 mx = event.button.x, my = event.button.y;
+//Not sure that this is the right way to handle this...
+// What we should do here is ensure that whatever has been clicked on gets moved to the
+// highest priority--in our current data schema that would be the end of the list... !!! FIX !!!
+//[DONE]
+
+/*
+
+We could do the following:
+
+- Go through list and find which window has been clicked on (if any). If more
+  than one is clicked on, take the one highest in the Z order (closer to the end
+  of the list).
+
+- If item is highest in Z order, pack click through to window and exit.
+
+- Otherwise, restore backing store on each window in reverse order.
+
+- Remove item clicked on from the list. Put removed item at the end of the list.
+
+- Go through list and pass click through to each window in the list. Also do a
+  blit to backing store and a Draw() for each window.
+
+Could also do a check (if not clicked on highest Z window) to see which windows
+it overlaps and just do restore/redraw for those that overlap. To wit:
+
+- Create new list containing only those windows that overlap the clicking on window.
+
+- Go through list and do a blit to backing store and a Draw() for each window.
+
+- Go through list and pass click through to each window in the list.
+
+*/
+
+#if 0
+#if 0
+                               for(i=windowList.begin(); i!=windowList.end(); i++)
+                                       (*i)->HandleMouseButton(event.button.x, event.button.y, true);
+#else
+// We use the 1st algorithm here, since it's simpler. If we need to, we can optimize
+// to the 2nd...
 
-                               if (mainWindow)
-                                       mainWindow->HandleMouseButton(mx, my, true);
+                               // Walk backward through the list and see if a window was hit.
+                               // This will automagically return us the window with the highest Z.
+
+                               std::list<Element *>::reverse_iterator ri;
+                               std::list<Element *>::iterator hit;// = windowList.end();
+
+                               for(ri=windowList.rbegin(); ri!=windowList.rend(); ri++)
+                               {
+                                       if ((*ri)->Inside(event.button.x, event.button.y))
+                                       {
+                                               // Here's a bit of STL weirdness: Converting from a reverse
+                                               // iterator to a regular iterator requires backing the iterator
+                                               // up a position after grabbing it's base() OR going forward
+                                               // one position with the reverse iterator before grabbing base().
+                                               // Ugly, but it get the job done...
+                                               hit = (++ri).base();
+                                               // Put it back where we found it, so the tests following this
+                                               // don't fail...
+                                               ri--;
+                                               break;
+                                       }
+                               }
+
+                               // If we hit the highest in the list, then pass the event through
+                               // to the window for handling. if we hit no windows, then pass the
+                               // event to all windows. Otherwise, we need to shuffle windows.
+
+//NOTE: We need to pass the click to all windows regardless of whether they're topmost or not...
+                               if (ri == windowList.rbegin())
+                               {
+                                       for(i=windowList.begin(); i!=windowList.end(); i++)
+                                               (*i)->HandleMouseButton(event.button.x, event.button.y, true);
+                               }
+                               else if (ri == windowList.rend())
+                               {
+                                       for(i=windowList.begin(); i!=windowList.end(); i++)
+                                               (*i)->HandleMouseButton(event.button.x, event.button.y, true);
+                               }
                                else
-                                       mainMenu->HandleMouseButton(mx, my, true);
+                               {
+// - Otherwise, restore backing store on each window in reverse order.
+                                       for(ri=windowList.rbegin(); ri!=windowList.rend(); ri++)
+                                               (*ri)->RestoreScreenFromBackstore();
+                                       // At this point, the screen has been restored...
+
+// - Remove item clicked on from the list. Put removed item at the end of the list.
+                                       windowList.push_back(*hit);
+                                       windowList.erase(hit);
+// - Go through list and pass click through to each window in the list. Also do a
+//  blit to backing store and a Draw() for each window.
+                                       for(i=windowList.begin(); i!= windowList.end(); i++)
+                                       {
+                                               // Grab bg into backstore
+                                               (*i)->SaveScreenToBackstore();
+                                               // Pass click
+                                               (*i)->HandleMouseButton(event.button.x, event.button.y, true);
+                                               // Draw?
+                                               (*i)->Draw();
+                                       }
+                               }
+#endif
+#endif
+/*
+A slightly different way to handle this would be to loop through all windows, compare
+all those above it to see if they obscure it; if so then subdivide it's update rectangle
+to eliminate drawing the parts that aren't shown. The beauty of this approach is that
+you don't have to care what order the windows are drawn in and you don't need to worry
+about the order of restoring the backing store.
+
+You *do* still need to determine the Z-order of the windows, in order to get the subdivisions
+correct, but that's not too terrible.
+
+Also, when doing a window drag, the coverage lists for all windows have to be regenerated.
+*/
+                               std::list<Element *>::reverse_iterator ri;
+                               bool movedWindow = false;
+
+                               for(ri=windowList.rbegin(); ri!=windowList.rend(); ri++)
+                               {
+                                       if ((*ri)->Inside(event.button.x, event.button.y))
+                                       {
+                                               // Remove item clicked on from the list & put removed item at the
+                                               // end of the list, thus putting the window at the top of the Z
+                                               // order. But IFF window is not already topmost!
+                                               if (ri != windowList.rbegin())
+                                               {
+                                                       windowList.push_back(*ri);
+                                                       // Here's a bit of STL weirdness: Converting from a reverse
+                                                       // iterator to a regular iterator requires backing the iterator
+                                                       // up a position after grabbing it's base() OR going forward
+                                                       // one position with the reverse iterator before grabbing base().
+                                                       // Ugly, but it get the job done...
+                                                       windowList.erase((++ri).base());
+                                                       movedWindow = true;
+                                               }
+
+                                               break;
+                                       }
+                               }
+
+//Small problem here: we should only pass the *hit* to the topmost window and pass
+//*misses* to everyone else... Otherwise, you can have overlapping draggable windows
+//and be able to drag both by clicking on a point that intersects both...
+//(though that may be an interesting way to handle things!)
+                               // Pass the click on to all windows
+                               for(i=windowList.begin(); i!=windowList.end(); i++)
+                                       (*i)->HandleMouseButton(event.button.x, event.button.y, true);
+
+//                             // & bail if nothing changed...
+                               if (movedWindow)
+//                                     return;
+{
+                               // Check for overlap/build coverage lists [O((n^2)/2) algorithm!]
+//One way to optimize this would be to only reset coverage lists from the point in
+//the Z order where the previous window was.
+                               for(i=windowList.begin(); i!=windowList.end(); i++)
+                               {
+                                       (*i)->ResetCoverageList();
+
+                                       // This looks odd, but it's just a consequence of iterator weirdness.
+                                       // Otherwise we could just stick a j+1 in the for loop below. :-P
+                                       std::list<Element *>::iterator j = i;
+                                       j++;
+
+                                       for(; j!=windowList.end(); j++)
+                                               (*i)->AdjustCoverageList((*j)->GetExtents());
+
+//                                     (*i)->HandleMouseButton(event.button.x, event.button.y, true);
+                                       (*i)->Draw();
+                               }
+}
                        }
                        else if (event.type == SDL_MOUSEBUTTONUP)
                        {
 #ifdef DEBUG_MAIN_LOOP
 WriteLog(" -- SDL_MOUSEBUTTONUP\n");
 #endif
-                               uint32 mx = event.button.x, my = event.button.y;
-
-                               if (mainWindow)
-                                       mainWindow->HandleMouseButton(mx, my, false);
-                               else
-                                       mainMenu->HandleMouseButton(mx, my, false);
+//Not sure that this is the right way to handle this...
+                               for(i=windowList.begin(); i!=windowList.end(); i++)
+                                       (*i)->HandleMouseButton(event.button.x, event.button.y, false);
+//I think we should only do topmost here...
+//Or should we???
+//                             windowList.back()->HandleMouseButton(event.button.x, event.button.y, false);
                        }
 #ifdef DEBUG_MAIN_LOOP
 else
index b67783ade503ca48e8c56c7ae932473f23371fea..05ab391b399209755b9fd045b13997ea84be64c9 100755 (executable)
@@ -8,7 +8,7 @@
 #define __GUI_H__
 
 #include <SDL.h>
-#include <vector>
+#include <list>
 
 class Menu;                                                                            // Now *this* should work, since we've got pointers...
 class MenuItems;
@@ -26,10 +26,12 @@ class GUI
                void Stop(void);
 
        private:
-               Menu * mainMenu;
+//             Menu * mainMenu;
                MenuItems * menuItem;
-               std::vector<Element *> windowList;
+               std::list<Element *> windowList;
                bool exitGUI;
+               bool showMouse;
+               SDL_Rect mouse, oldMouse;
 };
 
 #endif // __GUI_H__
index 99a8e352aa4cc2a132e0fdc85d6215ac77cb5852..53b333ddb16226151c81955bdf06761097f035d6 100755 (executable)
@@ -156,6 +156,47 @@ void DrawStringOpaque(SDL_Surface * screen, uint32 x, uint32 y, uint32 fg, uint3
        SDL_FreeSurface(chr);
 }
 
+bool RectanglesIntersect(SDL_Rect r1, SDL_Rect r2)
+{
+       // The strategy here is to see if any of the sides of the smaller rect
+       // fall within the larger.
+
+/*
+    +-----------------+ r1
+    |                 |
+    |   +------+ r2   |
+    |   |      |      |
+    |   |      |      |
+    |   +------+      |
+    |                 |
+    +-----------------+
+
+*/
+
+//This approach fails if r2 is inside of r1. !!! FIX !!! [DONE]
+       if (RectangleFirstInsideSecond(r2, r1))
+               return true;
+
+       if ((r1.x > r2.x && r1.x < (r2.x + r2.w))
+               || ((r1.x + r1.w) > r2.x && (r1.x + r1.w) < (r2.x + r2.w))
+               || (r1.y > r2.y && r1.y < (r2.y + r2.h))
+               || ((r1.y + r1.h) > r2.y && (r1.y + r1.h) < (r2.y + r2.h)))
+               return true;
+
+       return false;
+}
+
+bool RectangleFirstInsideSecond(SDL_Rect r1, SDL_Rect r2)
+{
+       if ((r1.x > r2.x             && (r1.x + r1.w) > r2.x)
+               && (r1.x < (r2.x + r2.w) && (r1.x + r1.w) < (r2.x + r2.w))
+               && (r1.y > r2.y          && (r1.y + r1.h) > r2.y)
+               && (r1.y < (r2.y + r2.h) && (r1.y + r1.h) < (r2.y + r2.h)))
+               return true;
+
+       return false;
+}
+
 
 //
 // Various GUI bitmaps
index 6382cc9c49186a292a91dcb8364412d0f2166efa..84da8741e217339eb56cfd2f2baf543d7f8d6fc9 100755 (executable)
@@ -48,7 +48,9 @@ uint32 GetFontHeight(void);
 void DrawStringTrans(SDL_Surface * screen, uint32 x, uint32 y, uint32 color, const char * text, ...);
 void DrawStringOpaque(SDL_Surface * screen, uint32 x, uint32 y, uint32 fg, uint32 bg, const char * text, ...);
 
-void DrawStringOpaqueSmall(SDL_Surface * screen, uint32 x, uint32 y, uint32 fg, uint32 bg, const char * text, ...);
+//Not sure these belong here, but there you go...
+bool RectanglesIntersect(SDL_Rect r1, SDL_Rect r2);
+bool RectangleFirstInsideSecond(SDL_Rect r1, SDL_Rect r2);
 
 // GUI bitmaps (exported)
 
index 96be146397091dc5a2a7f3e85eedf4aacd983313..96e45e71d5a4d32534f5ce5b3f8ffd203b89e2be 100755 (executable)
 #define MASK_A 0xFF000000
 #endif
 
-using namespace std;                                                           // For STL stuff
-
 //
 // Text edit class implementation
 //
 
 TextEdit::TextEdit(uint32 x/*= 0*/, uint32 y/*= 0*/, uint32 w/*= 0*/, uint32 h/*= 0*/,
-       string s/*= ""*/, Element * parent/*= NULL*/):
+       std::string s/*= ""*/, Element * parent/*= NULL*/):
        Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x40, 0x40, 0xFF, parent),
        activated(false), clicked(false), inside(false),
        img(NULL), text(s), caretPos(0), scrollPos(0),
@@ -227,7 +225,7 @@ void TextEdit::Notify(Element *)
 {
 }
 
-string TextEdit::GetText(void)
+std::string TextEdit::GetText(void)
 {
        return text;
 }
index 75b6cc1f8286b3209e711c8682dbcff203c80dfa..0f460eaa8f428411b109870bd2eed0803fff8ac4 100755 (executable)
 #include "guimisc.h"                                                           // Various support functions
 #include <algorithm>
 
+// Debug support...
+//#define DESTRUCTOR_TESTING
+
+// Rendering experiment...
+#define USE_COVERAGE_LISTS
+
 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
 #define MASK_R 0xFF000000
 #define MASK_G 0x00FF0000
@@ -30,8 +36,6 @@
 #define MASK_A 0xFF000000
 #endif
 
-using namespace std;                                                           // For STL stuff
-
 //
 // Window class implementation
 //
@@ -59,6 +63,9 @@ Window::Window(uint32 x/*= 0*/, uint32 y/*= 0*/, uint32 w/*= 0*/, uint32 h/*= 0*
 
 Window::~Window()
 {
+#ifdef DESTRUCTOR_TESTING
+printf("Inside ~Window()...\n");
+#endif
        for(uint32 i=0; i<list.size(); i++)
                if (list[i])
                        delete list[i];
@@ -100,6 +107,16 @@ void Window::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
 
 void Window::Draw(void)
 {
+#ifdef USE_COVERAGE_LISTS
+       // These are *always* top level and parentless, so no need to traverse up through
+       // the parent chain...
+       for(std::list<SDL_Rect>::iterator i=coverList.begin(); i!=coverList.end(); i++)
+               SDL_FillRect(screen, &(*i), bgColor);
+
+       // Handle the items this window contains...
+       for(uint32 i=0; i<list.size(); i++)
+               list[i]->Draw();
+#else
        // These are *always* top level and parentless, so no need to traverse up through
        // the parent chain...
        SDL_FillRect(screen, &extents, bgColor);
@@ -107,6 +124,7 @@ void Window::Draw(void)
        // Handle the items this window contains...
        for(uint32 i=0; i<list.size(); i++)
                list[i]->Draw();
+#endif
 
 //Prolly don't need this since the close button will do this for us...
        needToRefreshScreen = true;
@@ -117,7 +135,9 @@ void Window::Notify(Element * e)
        if (e == closeButton)
        {
                SDL_Event event;
-               event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
+               event.type = SDL_USEREVENT;
+               event.user.code = WINDOW_CLOSE;
+               event.user.data1 = (void *)this;
                SDL_PushEvent(&event);
        }
 }
index 9c2383392ba7602984175003b9f9811171186f02..a98c16f7b677dc3e9692384b491967c40bce6d8e 100755 (executable)
@@ -15,7 +15,6 @@
 //However, the Atari version *does* occassionally pick strength while the Apple
 //versions do not--which would seem to indicate a bug either in the RNG algorithm,
 //the 65C02 core, or the Apple hardware. Need to investigate all three!
-//[As it turns out, it was a problem with the Apple RNG written by Origin. Bad Origin!]
 
 #define __DEBUG__
 //#define __DEBUGMON__
@@ -918,10 +917,10 @@ static void OpDE(void)                                                    // DEC ABS, X
 Here's one problem: DEX is setting the N flag!
 
 D3EE: A2 09          LDX   #$09                [PC=D3F0, SP=01F7, CC=---B-I-C, A=01, X=09, Y=08]
-D3F0: 98             TYA                       [PC=D3F1, SP=01F7, CC=N--B-I-C, A=08, X=09, Y=08]
-D3F1: 48             PHA                       [PC=D3F2, SP=01F6, CC=N--B-I-C, A=08, X=09, Y=08]
+D3F0: 98             TYA               [PC=D3F1, SP=01F7, CC=N--B-I-C, A=08, X=09, Y=08]
+D3F1: 48             PHA               [PC=D3F2, SP=01F6, CC=N--B-I-C, A=08, X=09, Y=08]
 D3F2: B5 93          LDA   $93,X               [PC=D3F4, SP=01F6, CC=---B-IZC, A=00, X=09, Y=08]
-D3F4: CA             DEX                       [PC=D3F5, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08]
+D3F4: CA             DEX               [PC=D3F5, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08]
 D3F5: 10 FA          BPL   $D3F1               [PC=D3F7, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08]
 D3F7: 20 84 E4       JSR   $E484               [PC=E484, SP=01F4, CC=N--B-I-C, A=00, X=08, Y=08]
 
@@ -1131,7 +1130,6 @@ JSR       Absolute        JSR Abs         20      3       6
 //This is not jumping to the correct address... !!! FIX !!! [DONE]
 static void Op20(void)                                                 // JSR
 {
-// The whole ret - 1 probably stems from a fetch/push/fetch/push sequence...
        uint16 addr = RdMemW(regs.pc);
        regs.pc++;                                                                      // Since it pushes return address - 1...
        regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);