QB64 Phoenix Edition
Memory problem with hardware acceleration. [Resolved] Thanks Mark! - Printable Version

+- QB64 Phoenix Edition (https://staging.qb64phoenix.com)
+-- Forum: QB64 Rising (https://staging.qb64phoenix.com/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://staging.qb64phoenix.com/forumdisplay.php?fid=3)
+---- Forum: Help Me! (https://staging.qb64phoenix.com/forumdisplay.php?fid=10)
+---- Thread: Memory problem with hardware acceleration. [Resolved] Thanks Mark! (/showthread.php?tid=980)



Memory problem with hardware acceleration. [Resolved] Thanks Mark! - Pete - 10-17-2022

This example will not write to your drive. It is a high score hardware overlay, but I stripped out the file stuff.

The overlay is called repeatedly to mimic a flashing cursor. See CALL underline() sub.

What I find is the repeated call keeps copying a new image, one with the cursor showing, and one hidden. That's just 2 images, but since it keeps getting called, instead of switching images (I don;t no how of if that's possible) it just keeps making more of the same alternating screen copy images, which keeps multiplying the memory usage until other OS systems are affected.

You can monitor what I'm talking about by running Windows Task Manager with this code.

Now according to the wiki, I can't use _FREEIMAGE in the loop because I'm not changing screens. I do use it after the original screen is reactivated.

So is there a way to accomplish this flashing cursor effect in the hardware image without burning up the system's memory?

Code: (Select All)
$COLOR:32
REM Main
f1 = 22 ' Sets font size to 22 and calculates the max screen height and width for your desktop.
h = (_DESKTOPHEIGHT - 60) \ f1
w = _DESKTOPWIDTH \ (f1 / 1.66)
WIDTH w, h
_SCREENMOVE 0, 0
fontpath$ = ENVIRON$("SYSTEMROOT") + "\fonts\lucon.ttf" 'Find Windows Folder Path.
font& = _LOADFONT(fontpath$, f1, "monospace")
_FONT font&
_DELAY .25
_RESIZE ON , _SMOOTH ' Allows resizing. Note: this is for slight adjustments. As of this version there is no compensatory function to change the font size during screen size changes.

DIM SHARED Overlay, g.population
g.population = 100000

CALL displayhighscores

SUB displayhighscores
    hardware_top = v.top + 7
    hardware_left = v.left + 35
    score$ = LTRIM$(STR$(g.population))

    DIM hs AS STRING * 25
    REDIM highscore$(6), hsdata$(6)
    DO
        FOR i = 1 TO 5
            hsdata$(i) = SPACE$(25)
        NEXT

        IF VAL(score$) > VAL(highscore$(5)) THEN

            GOSUB hiscore

            i = 14
            OUT &H3C8, 0
            OUT &H3C9, 20 - i
            OUT &H3C9, 20 - i
            OUT &H3C9, 20 - i

            OUT &H3C8, 8
            OUT &H3C9, 30 - i
            OUT &H3C9, 30 - i
            OUT &H3C9, 30 - i

            OUT &H3C8, 7
            OUT &H3C9, 30 - i
            OUT &H3C9, 30 - i
            OUT &H3C9, 30 - i

            OUT &H3C8, 3
            OUT &H3C9, 30 - i
            OUT &H3C9, 30 - i
            OUT &H3C9, 30 - i

            GOSUB hardware_overlay

            COLOR White, 0
            t$ = msg$
            PSLC 4.6, 41 - LEN(msg$) \ 2, t$

            lscr = hardware_left + 6
            z3 = TIMER
            WHILE -1
                initials$ = "": i = 0: nxt = 0
                COLOR , _RGB(24, 24, 24): t$ = "   " ' Blank initials for redo. Okay to blank at start.
                PSL hardware_top + 2 + rank * 2, lscr, t$
                _DISPLAY
                DO
                    _LIMIT 30
                    IF ABS(z3 - TIMER) > .3 THEN ' Flashing cursor
                        underline hardware_top + 2 + rank * 2, lscr + nxt, 0
                        _DISPLAY
                        z3 = TIMER
                    END IF

                    ky$ = UCASE$(INKEY$)
                    IF LEN(ky$) THEN
                        IF ky$ = CHR$(13) THEN
                            kflag = 3
                        ELSEIF ky$ = CHR$(8) AND LEN(initials$) THEN
                            kflag = 2
                        ELSEIF ky$ = CHR$(27) THEN
                            kflag = 4
                        ELSEIF ky$ >= "A" AND ky$ <= "Z" AND LEN(initials$) < 3 THEN
                            initials$ = initials$ + ky$
                            kflag = 1
                        ELSE
                            ky$ = "": kflag = 0
                        END IF
                    END IF

                    SELECT CASE kflag
                        CASE 1
                            COLOR , _RGB(24, 24, 24)
                            PSL hardware_top + 2 + rank * 2, lscr + nxt, " "
                            COLOR Yellow
                            SOUND 1000, .1
                            PSL hardware_top + 2 + rank * 2, lscr + nxt, ky$
                            underline hardware_top + 2 + rank * 2, lscr + nxt, -1
                            nxt = nxt + 1
                            underline hardware_top + 2 + rank * 2, lscr + nxt, 0
                            _DISPLAY
                            kflag = 0
                        CASE 2
                            COLOR , _RGB(24, 24, 24)
                            underline hardware_top + 2 + rank * 2, lscr + nxt, -1
                            initials$ = MID$(initials$, 1, LEN(initials$) - 1)
                            nxt = nxt - 1
                            PSL hardware_top + 2 + rank * 2, lscr + nxt, " "
                            COLOR Yellow
                            SOUND 1000, .1
                            underline hardware_top + 2 + rank * 2, lscr + nxt, 0
                            _DISPLAY
                            kflag = 0
                        CASE 3
                            _DELAY 1
                            l$ = "8"
                            n$ = "n24": PLAY "L" + l$ + n$
                            n$ = "n28": PLAY "L" + l$ + n$
                            n$ = "n28": PLAY "L" + l$ + n$
                            l$ = "7"
                            n$ = "n31": PLAY "L" + l$ + n$
                            l$ = "9"
                            n$ = "n28": PLAY "L" + l$ + n$
                            l$ = "3"
                            n$ = "n31": PLAY "L" + l$ + n$
                            kflag = 1
                            _DELAY 1: EXIT DO
                        CASE 4
                            EXIT WHILE
                    END SELECT
                LOOP
                hsname$ = initials$

                MID$(hsdata$(rank), 5, 3) = hsname$ + SPACE$(3 - LEN(hsname$))
                OPEN "ascii-invaders-high-score.dat" FOR RANDOM AS #1 LEN = 25
                FOR i = 1 TO 5
                    hs = hsdata$(i)
                    IF LEFT$(hs, 1) = "" THEN MID$(hs, 1, 2) = "0" + LTRIM$(STR$(i))
                    PUT #1, i, hs
                NEXT
                CLOSE #1
                EXIT WHILE
            WEND

            _DISPLAY ' Remove scoreboard.
            _DELAY .5
            _FREEIMAGE Overlay

            _DEST 0 'Reset dest back to the normal screen 0.

            _AUTODISPLAY
            PALETTE
            _DELAY .5

            EXIT DO
        ELSE
            EXIT DO ' Not in the top 5 highest scores so exit sub.
        END IF
    LOOP
    EXIT SUB

    hardware_overlay:
    Overlay = _NEWIMAGE(_WIDTH * _FONTWIDTH, _HEIGHT * _FONTHEIGHT, 32)

    _DEST Overlay
    _DISPLAY ' Turn autodisplay off.

    font = _LOADFONT("lucon.ttf", 24, "monospace")
    IF font <= 0 THEN font = 16
    _FONT font

    bxy% = hardware_top
    bxx% = hardware_left

    IF VAL(score$) > VAL(highscore$(1)) THEN
        t$ = "HIGH SCORE! Enter Initials!"
    ELSE
        t$ = "Top 5 Score Enter Initials!"
    END IF

    COLOR White, 0
    PSL bxy% + .8, bxx% + 1, t$

    COLOR Yellow, 0
    t$ = " " + CHR$(218) + STRING$(27, CHR$(196)) + CHR$(191) + " "
    PSL bxy%, bxx% - 1, t$
    FOR i = 1 TO 12
        t$ = " " + CHR$(179) + STRING$(27, CHR$(32)) + CHR$(179) + " "
        PSL bxy% + i, bxx% - 1, t$
    NEXT
    t$ = " " + CHR$(192) + STRING$(27, CHR$(196)) + CHR$(217) + " "
    PSL bxy% + i, bxx% - 1, t$

    bxy% = hardware_top + 1
    COLOR Black, Yellow
    t$ = "    NAME   SCORE    DATE   "
    PSL bxy% + 1, bxx% + 1, t$

    COLOR Yellow, 0
    FOR i = 1 TO 5
        t$ = hsdata$(i)
        PSL bxy% + 1 + i * 2, bxx% + 2, t$
    NEXT
    _DISPLAY
    RETURN

    hiscore:
    FOR i = 1 TO 5
        IF VAL(score$) > VAL(highscore$(i)) THEN rank = i: EXIT FOR
    NEXT

    hsdata$(6) = SPACE$(25)
    MID$(hsdata$(6), 10, 6) = score$
    MID$(hsdata$(6), 18, 8) = MID$(DATE$, 1, 6) + MID$(DATE$, 9, 2)
    highscore$(6) = score$
    FOR i = 1 TO 6
        FOR j = 1 TO 6
            IF i <> j THEN
                IF VAL(highscore$(i)) > VAL(highscore$(j)) THEN
                    SWAP highscore$(i), highscore$(j)
                    SWAP hsdata$(i), hsdata$(j)
                END IF
            END IF
        NEXT
    NEXT
    FOR i = 1 TO 5
        MID$(hsdata$(i), 1, 2) = "0" + LTRIM$(STR$(i))
    NEXT
    RETURN
END SUB

SUB PSLC (y!, x, t$)
    _PRINTSTRING ((x - 1) * 8, (y! - 1) * 16), t$
END SUB

SUB PSL (y!, x, t$)
    _PRINTSTRING ((x - 1) * _FONTWIDTH, (y! - 1) * _FONTHEIGHT), t$
    Overlay_Hardware = _COPYIMAGE(Overlay, 33)
    _PUTIMAGE (0, 0), Overlay_Hardware
END SUB

SUB underline (y, x, uflag)
    STATIC ucnt
    ucnt = -ucnt - 1
    IF ucnt OR uflag THEN
        LINE ((x - 1) * _FONTWIDTH, y * _FONTHEIGHT)-((x - 1) * _FONTWIDTH + 12, y * _FONTHEIGHT), _RGB(24, 24, 24), BF
    ELSE
        LINE ((x - 1) * _FONTWIDTH, y * _FONTHEIGHT)-((x - 1) * _FONTWIDTH + 12, y * _FONTHEIGHT), Yellow, BF
    END IF

    Overlay_Hardware = _COPYIMAGE(Overlay, 33)
    _PUTIMAGE (0, 0), Overlay_Hardware
END SUB



Pete


RE: Memory problem with hardware acceleration. - bplus - 10-17-2022

Well I am not buying your reason not to use _FreeImage:
Code: (Select All)
Sub PSL (y!, x, t$)
    _PrintString ((x - 1) * _FontWidth, (y! - 1) * _FontHeight), t$
    Overlay_Hardware = _CopyImage(Overlay, 33)
    _PutImage (0, 0), Overlay_Hardware
    _FreeImage Overlay_Hardware
End Sub

Sub underline (y, x, uflag)
    Static ucnt
    ucnt = -ucnt - 1
    If ucnt Or uflag Then
        Line ((x - 1) * _FontWidth, y * _FontHeight)-((x - 1) * _FontWidth + 12, y * _FontHeight), _RGB(24, 24, 24), BF
    Else
        Line ((x - 1) * _FontWidth, y * _FontHeight)-((x - 1) * _FontWidth + 12, y * _FontHeight), Yellow, BF
    End If

    Overlay_Hardware = _CopyImage(Overlay, 33)
    _PutImage (0, 0), Overlay_Hardware
    _FreeImage Overlay_Hardware
End Sub

Memory seems to be holding steady.

This seems pretty complicated way to get flashing cursor, can't it be done in screen 0 and if not in Screen 0 use a line?
OTOH I don't follow all that you do but you put together some nice looking screens.


RE: Memory problem with hardware acceleration. - Pete - 10-17-2022

Hi Mark,

BINGO. +1.

That worked. QB64 help says you can't free it until you exit the screen. My goof was I was experimenting trying to free it by using...

_FREEIMAGE overlay

instead of...

_FREEIMAGE hardware_overlay

The former was causing errors to pop up.

Thanks!

Pete

PS Yes, you can easily mimic cursor flashing in SCREEN 0, which has a flashing text cursor, SCREEN 12 (no cursor), etc. but it is a bit more involved when using a hardware image overlay. I'm doing it this way for the overlap effect.