Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 22:29 21 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : WIP CMM2 Gen 2: A bit of fun - CMM2 File Manager

     Page 1 of 2    
Author Message
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 367
Posted: 09:57pm 18 Nov 2024
Copy link to clipboard 
Print this post

I know - The CMM2 already has a fully working file manager. But this started as a bit of fun. It was originally going to be a GUI for a graphical text adventure like the old Magnetic Scrolls "The Pawn" or "Guild of Thieves".

Then it sort of morphed into a front end for launching programs or managing files.

It's a work in progress, so it almost certainly has a few bugs, and there's a lot more features I want to add to it (Ram Disk, Networking etc.), but I want to spend time on some games dev, so it's going back on the shelf for the time being.

It happily handles files and directories being moved, renamed. Launching programs. Copying links for folders to the desktop (for easier launching) and it has a Rubbish bin for deleted files, so that they can be recovered.



It does require a CMM2 Gen 2 as it uses the mouse. It is by no means intended to be an operating system - I 100% still prefer that the CMM2 boots straight to BASIC and not to an OS. But part of my thinking was that if you did want to make a system that was easier for the grandkids to launch games etc. then this would suffice. It would be simple to disable the disruptive commands (Delete, Move, rename etc.) so that it was only a file launcher.

Video of it in action here:
https://1drv.ms/v/s!AnkZn9N9Pt1fyMISsNqOildOm0r6jA?e=cCDuMg

Download source here:
https://1drv.ms/u/s!AnkZn9N9Pt1fyMIRhgu0qZTfhJjlIQ?e=dw0vZn
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 367
Posted: 09:58pm 18 Nov 2024
Copy link to clipboard 
Print this post

Here's the source if you don't want to download the .zip file.

OPTION EXPLICIT
' This program is split in to the following sections
'     Variable Initialisation
'     Main Loop
'     Mouse Handling (C1_xxxx)
'     Main Screen Graphics (C2_xxxx)
'     Window Graphics (C3_xxxx)
'     Window Logic (C4_xxxx)
'     Window Contents Array (C5_xxxx)
'     Text Input Window (C6_xxxx)
'     Menu Graphics and Logic (C7_xxxx)
'     Generic Graphics (C8_xxxx)
'     File Handling (C9_xxxx)


'********************************************************************************************
'                                       VARIABLE INITIALISATION
'********************************************************************************************
CONST FOREGROUND1=RGB(WHITE)
CONST BACKGROUND1=RGB(40,40,80) ' Nice dark blue for desktop
CONST BACKGROUND2=RGB(87,88,90) ' Menu Bar
CONST BACKGROUND3=RGB(80,80,160) ' background of windows
CONST MENUBACKGROUND1=RGB(67,68,183)
CONST MENUBACKGROUND2=RGB(47,48,100)
CONST MENUFOREGROUND1=RGB(255,255,255)

DIM INTEGER MouseX%, MouseY%, MouseLeft%, MouseRight%, MouseDx%, MouseDy%, LastMouseX%, LastMouseY%, LastMouseLeft%
DIM INTEGER WindowClickedOn%, WindowSizeChanging%, ScrollbarDragging%
DIM INTEGER SelectedDesktopIcon%
DIM INTEGER I%, Id%, Wid%
DIM INTEGER SystemMenuOpenState%
DIM STRING OriginalWorkingDirectory$     ' Used to remember what the working directory was on startup

' Upto 100 icons and windows
CONST WIN_ID=0
CONST WIN_X=1
CONST WIN_Y=2
CONST WIN_W=3
CONST WIN_H=4
CONST WIN_TYPE=5
CONST WIN_FIRSTICON=6
CONST WIN_SCROLLBARTOP=7
CONST WIN_ICONCOUNT=8
DIM INTEGER IconData%(100,6)
CONST ICON_ID=0
CONST ICON_X=1
CONST ICON_Y=2
CONST ICON_W=3
CONST ICON_H=4
CONST ICON_STATUS=5  'status is 0 - None, 1 - Open

DIM STRING IconName$(100)
DIM INTEGER WindowData%(100,9) ' Data is saved as IconId,x,y,w,h,type where type is 1 = DriveFolder
DIM STRING WindowPaths$(100) ' Path for each drive folder window
DIM STRING WindowContents$(100,10)
DIM INTEGER SelectedIconsInTopWindow%(1000)
DIM INTEGER WindowLeft%, WindowRight%, WindowTop%, WindowBottom%, WindowHeight%, WindowWidth%
DIM STRING DebugLine$, DebugLine2$
DIM INTEGER DblClk_TimeSinceLastClick%, DblClk_LastClickedIndex%
DIM STRING FilenamesToCopy$(1000), PathToCopyFrom$
DIM STRING GUIMessage$
DIM STRING GUIMenuOptions$(20)
DIM INTEGER GUIMenuOptionsParameters%(100)  'id,x,y,width,height of each button
DIM INTEGER GUIMenuParameters%(5) ' Menu id (0 is no menu), x,y,width,height
DIM INTEGER GUIMenuCurrentItem%    ' The item the mouse is hovering over (-1 for none)
DIM INTEGER ScrollTop%, ScrollBottom%
DIM STRING SDCardStatus$
DIM INTEGER SDCardOK%
DIM INTEGER TextInputWindowType%=0   ' 0 - None, 1- Rename Directory or File, 2-New Directory
DIM STRING TextInputWindowOriginal$  ' The original name of the file or directory to be renamed
DIM STRING TextInputWindowContents$  ' The new name for the file or directory (user input)
DIM INTEGER Key% ' Stores keycode of last key pressed
DIM INTEGER NeedToRefreshScreenFlag% ' If 1, then the screen will be redrawn
DIM INTEGER KeyDebounce%
DIM INTEGER EnterPressed%=0           ' Remembers if Enter pressed on TextInputWindow
DIM INTEGER EscapePressed%=0          ' Remembers if Escape pressed on TextInputWindow
CONST MENU_ID=0
CONST MENU_X=1
CONST MENU_Y=2
CONST MENU_W=3
CONST MENU_H=4

'********************************************************************************************
'                                       MAIN LOOP
'********************************************************************************************

OriginalWorkingDirectory$=CWD$  ' Remember the Working Directory so we can restore it on exit

ON ERROR SKIP 1   ' If the mouse isn't initialised the following line will throw an error
CONTROLLER MOUSE OPEN 0,C1_LeftButton,C1_RightButton
IF MM.ERRNO=16 THEN
 PRINT "There was a problem initialising the mouse. Make sure a PS2 compatible mouse is plugged in."
 PRINT "You may need to eneter the command 'OPTION MOUSE 0' to enable the mouse."
 END
END IF

'MODE 10,8   '848x480   - Doesn't work well on my Asus monitor
MODE 11,8   ' 1280x720
FONT 7

PAGE DISPLAY 0
GUI CURSOR ON 0,0,0,FOREGROUND1
GUI CURSOR LINK MOUSE
PAGE WRITE 2
LOAD PNG "A:\GUI\img\icons2",0,0
PAGE WRITE 0
FOR I%=0 TO 99
 IconData%(I%,ICON_ID)=0:IconData%(I%,ICON_X)=0:IconData%(I%,ICON_Y)=0:IconData%(I%,ICON_W)=0
 IconData%(I%,ICON_H)=0:IconData%(I%,ICON_STATUS)=0
NEXT I%
FOR I% = 0 TO 99
 WindowData%(I%,WIN_Id)=0:WindowData%(I%,WIN_X)=0:WindowData%(I%,WIN_Y)=0
 WindowData%(I%,WIN_W)=0:WindowData%(I%,WIN_H)=0:WindowData%(I%,WIN_TYPE)=0
 WindowData%(I%,WIN_FIRSTICON)=0:WindowData%(I%,WIN_SCROLLBARTOP)=0:WindowData%(I%,WIN_ICONCOUNT)=0
NEXT I%

C2_RedrawScreen
C9_CopyGUIFilesToDisk ' Make sure Rubbish directory exists

DO
 ' Read the mouse
 MouseX% = MOUSE(x,0)
 MouseY% = MOUSE(y,0)
 MouseLeft% = MOUSE(l,0)
 MouseRight% = MOUSE(r,0)

 MouseDx% = MouseX% - LastMouseX%    ' Calculate how much the Mouse X has moved since the last scan
 MouseDy% = MouseY% - LastMouseY%    ' Calculate how much the Mouse Y has moved since the last scan
 LastMouseX% = MouseX%:LastMouseY% = MouseY%
 IF MouseLeft% = 1 AND LastMouseLeft% = 1 THEN
   IF MouseDx% <> 0 OR MouseDy% <> 0 THEN   ' We are dragging the mouse
     IF WindowClickedOn% <> -1 THEN
       Wid%=WindowClickedOn%   ' TODO Wid is always 0???
       IF ScrollbarDragging% = 1 THEN      ' Scrollbar is being dragged
         ScrollBottom% = WindowData%(Wid,WIN_H)-32
         WindowData%(Wid%,WIN_SCROLLBARTOP) = WindowData%(wid,WIN_SCROLLBARTOP) + MouseDy%
         WindowData%(Wid%,WIN_ICONCOUNT) = -1  ' Force the icons to be recalculated
         IF WindowData%(Wid%,WIN_SCROLLBARTOP) < 0 THEN WindowData%(Wid%,WIN_SCROLLBARTOP) = 0
         IF WindowData%(Wid%,WIN_SCROLLBARTOP) > ScrollBottom% THEN WindowData%(Wid%,WIN_SCROLLBARTOP) = ScrollBottom%
       ELSE ' Window is being dragged
         WindowData%(Wid%,WIN_X) = WindowData%(Wid%,WIN_X) + MouseDx%
         WindowData%(Wid%,WIN_Y) = WindowData%(Wid%,WIN_Y) + MouseDy%
       END IF
       C2_RedrawScreen
     END IF
     IF WindowSizeChanging% <> -1 THEN ' Window is being resized. It is always the topmost window
       WindowData%(0,WIN_W) = WindowData%(0,WIN_W) + MouseDx%
       WindowData%(0,WIN_H) = WindowData%(0,WIN_H) + MouseDy%
       WindowData%(Wid%,WIN_ICONCOUNT) = -1     ' Force the icons to be recalculated          
       IF WindowData%(Wid%,WIN_W) < 100 THEN WindowData%(Wid%,WIN_W) = 100  ' Minimum window width of 100
       IF WIndowData%(Wid%,WIN_H) < 100 THEN WindowData%(Wid%,WIN_H) = 100  ' Minimum window height of 100
       C2_RedrawScreen
     END IF
   END IF
 END IF

 IF mouseLeft% = 0 THEN WindowClickedOn% = -1:WindowSizeChanging% = -1:ScrollBarDragging% = -1
 lastMouseLeft% = mouseLeft%

 C7_RefreshGUIMenu

 IF KEYDOWN(0) = 0 THEN KeyDebounce% = 1
 FOR I% = 1 TO KEYDOWN(0)
   Key% = KEYDOWN(I%)
   IF TextInputWindowType% <> 0 THEN    ' The user is typing in the new name for a file or folder
     IF KeyDebounce% = 1 THEN
       NeedToRefreshScreenFlag% = 1
       IF key% = 8 AND LEN(TextInputWindowContents$) > 0 THEN   ' Backspace
         TextInputWindowContents$ = MID$(TextInputWindowContents$,1,LEN(TextInputWindowContents$)-1)
       ENDIF
       IF Key% > 32 AND Key% < 127 AND LEN(TextInputWindowContents$) < 32 THEN
         TextInputWindowContents$ = TextInputWindowContents$ + CHR$(key%)
       ENDIF
       IF Key% = 10 OR Key% = 13 THEN     ' Enter key pressed
         EnterPressed% = 1
         C6_ProcessTextInputWindow
       ENDIF
       IF Key% = 27 THEN
         EscapePressed% = 1
         C6_ProcessTextInputWindow
       ENDIF  
       KeyDebounce% = 0
     ENDIF
   ELSE
     IF Key%=67 OR Key%=99 THEN        ' C is 67 or 99 (upper/lower case)
       C9_CopyButtonPressed
     END IF
     IF Key% = 80 OR Key% = 112 THEN   ' P is 80 or 112 (upper/lower case)
       C9_PasteButtonPressed
     END IF
   END IF
 NEXT I%

 C9_ReadInsertedSDCard
 IF NeedToRefreshScreenFlag% THEN C2_RedrawScreen
 NeedToRefreshScreenFlag% = 0
LOOP

'********************************************************************************************
'                                       MOUSE HANDLING C1_xxxx
'********************************************************************************************

SUB C1_LeftButton   ' Interupt on left button click
 C1_HandleMouseClick
END SUB

SUB C1_RightButton  ' Interupt on right button click
 C1_HandleMouseClick
END SUB

SUB C1_HandleMouseClick
 STATIC INTEGER IgnoreInterrupt%=0  ' Important that this is a static
 STATIC INTEGER IconsPerRow%
 STATIC INTEGER LocalIconId%, RowCalc%
 STATIC INTEGER debounceTimer%
 LOCAL INTEGER x%,y%,w%

 IF Timer - debounceTimer% < 500 THEN EXIT SUB  ' Clicking on a menu disables the click event for half a second

 IF IgnoreInterrupt% = 1 THEN EXIT SUB
 IgnoreInterrupt% = 1  ' Make sure this interrupt doesn't fire again until it is finished processing the last call

 MouseX% = MOUSE(X,0)
 MouseY% = MOUSE(Y,0)
 MouseLeft% = MOUSE(L,0)
 MouseRight% = MOUSE(R,0)

 ' The TextInputWindow is modal - i.e. all other clicks are ignored until it is closed
 IF TextInputWindowType% <> 0 THEN
   C6_ProcessTextInputWindow
   IgnoreInterrupt% = 0 ' Re-enable this interrupt
   EXIT SUB    
 END IF

 C7_RefreshGUIMenu

 'Check if it's a menu click (menu's are topmost if there is no TextInputWindow)
 IF GuiMenuCurrentItem% <> -1 THEN
   DebounceTimer% = Timer  ' To prevent unwanted clicks - clicking on a menu disables the mouse click for half a second

   IF GUIMenuParameters%(MENU_ID) = 1 THEN ' File copy Menu   -Copy,Paste,Make Dir and Delete
     IF GuiMenuCurrentItem% = 0 THEN ' Copy
       C9_CopyButtonPressed
       IgnoreInterrupt% = 0:C7_CloseMenu:EXIT SUB ' The click has been handled - no need to go further
     END IF
     IF GuiMenuCurrentItem% = 1 AND PathToCopyFrom$ <> WindowPaths$(0) THEN ' Paste - Check we're not pasting back to the source directory
       C9_PasteButtonPressed
       IgnoreInterrupt% = 0:C7_CloseMenu:EXIT SUB ' The click has been handled - no need to go further
     ENDIF
     IF GuiMenuCurrentItem% = 2 THEN ' Move
       C9_MoveSelectedFiles WindowPaths(0)
       IgnoreInterrupt% = 0:C7_CloseMenu:EXIT SUB ' The click has been handled - no need to go further
     ENDIF
     IF GuiMenuCurrentItem% = 3 THEN ' Make Directory
       C6_OpenTextInputWindowAsNewDir
     ENDIF
     IF GuiMenuCurrentItem% = 4 THEN ' Link to Desktop
       C9_AddSelectedIconsToDesktop
     ENDIF
     IF GuiMenuCurrentItem% = 6 THEN ' Rename
       C6_OpenTextInputWindowAsRename
     ENDIF
     IF GuiMenuCurrentItem% = 7 THEN ' Delete
       C9_DeleteSelectedFiles
       IgnoreInterrupt% = 0:C7_CloseMenu:EXIT SUB ' The click has been handled - no need to go further
     ENDIF
   END IF
   IF GUIMenuParameters%(MENU_ID) = 2 THEN ' Desktop icon menu - Remove from desktop
     IF GuiMenuCurrentItem% = 0 THEN ' Remove from desktop
       C9_RemoveSelectedIconFromDesktop
     END IF
   END IF
 ENDIF

 C7_CloseMenu  ' If we are here, then the user clicked somewhere on the screen. If a menu was open, then close it

 DebugLine2$ = ""
 IF MouseY% < 15 THEN   ' Top of screen Menu Bar Click
   IF MouseX% < 40 THEN ' System Menu Open/Close
     C7_SystemMenuOpenClose
   END IF
   IF MouseX% > MM.HRES - 20 THEN ' Close program
     IF MM.INFO(EXISTS DIR OriginalWorkingDirectory$)=1 THEN
       CHDIR OriginalWorkingDirectory$  ' Remember to put the user back in the working directory they started from
     END IF
     CLS
     END
   END IF
 ELSE
   'Check if this was a window the user clicked on
   FOR I% = 0 TO 99
     IF WindowData%(I%,WIN_ID) <> 0 THEN
       WindowLeft% = WindowData%(I%,WIN_X):WindowRight% = WindowData%(I%,WIN_X) + WindowData%(I%,WIN_W)
       WindowTop% = WindowData%(I%,WIN_Y):WindowBottom% = WIndowData%(I%,WIN_Y) + WindowData%(I%,WIN_H)
       WindowHeight% = WindowTop% - WindowBottom%:WindowWidth% = WindowRight% - WindowLeft%
       IF MouseY% > WindowTop% AND MouseY% < WindowBottom% THEN
         IF MouseX% > WindowLeft% AND MouseX% < WindowRight% THEN
           DebugLine2$ = "Window Found"
           IF I% <> 0 THEN  ' Is this window topmost - if not make it topmost (Move to position 0)
             C4_MoveWindowToTop I%
             C4_ClearSelectedIcons   ' Unselect and selected icons - i.e. no icons are selected
           END IF
           WindowClickedOn% = 0   ' Topmost window clicked on (0 is always the topmost)
           ' Is it the windows resize icon
           IF MouseX% > WindowRight% - 15 AND MouseY% > WindowBottom% - 15 THEN
             WindowSizeChanging% = 0
             WindowClickedOn% = -1
           ELSEIF MouseX% < WindowLeft% + 40 AND MouseY% < WindowTop% + 15 THEN 'Did the user click on the back button?
             C4_ClearSelectedIcons   ' Unselect and selected icons - i.e. no icons are selected
             WindowPaths$(0) = C9_GetParentPath(WindowPaths$(0))  ' Move to the parent folder
             C5_UpdateWindowContents 0   ' Read the contents of the new folder from disk
           ELSEIF MouseX% > WindowRight% - 20 AND MouseY% < WindowTop% + 15 THEN
             'Did the user just click on the close button
             C4_CloseWindowWithIconId(WindowData%(0,WIN_ID))  ' The active window is always 0 - close it        
             WindowClickedOn% = -1   ' No window selected
           ELSEIF MouseX% > WindowRight% - 10 AND MouseY% > WindowTop% + 16 AND MouseY% < WindowBottom% - 22 THEN
             ' User has clicked on the scrollbar
             ScrollbarDragging% = 1
           ELSEIF MouseY% > WindowTop% + 15 THEN ' They're not clicking on the window toolbar  
             ' Check and see if they clicked on a file or folder
             IconsPerRow% = (WindowWidth% - 4 - 30)/60  ' We subtract 1 for cases where the width is an exact multiple of 60. And the 30 is because basic rounds up
             IF MouseX% - WindowLeft% < IconsPerRow% * 60 THEN ' Check they are actually in the icon area
               LocalIconId% = (MouseX% - WindowLeft% + 4 - 30)/60 ' Calculate the column
               RowCalc% = (MouseY% - WindowTop% - 35)/50
               LocalIconId% = LocalIconId% + (RowCalc% * IconsPerRow%) + WindowData%(0, WIN_FIRSTICON)
               IF MouseLeft% = 1 THEN  ' This is a left mouse click                
                 IF TIMER - DblClk_TimeSinceLastClick% < 500 AND DblClk_LastClickedIndex% = LocalIconId% THEN
                   ' This is a double click event
                   C1_DoubleClickEvent 0, LocalIconId%                  
                 ELSE
                   C4_AddIconToSelectedIcons LocalIconId%, 1 ' The 1 at the end allows for de-selection
                 END IF
               
                 DblClk_LastClickedIndex% = LocalIconId%
                 DblClk_TimeSinceLastClick% = TIMER
               END IF
               IF MouseRight% = 1 THEN
                 IF PathToCopyFrom$ = WindowPaths$(0) OR PathToCopyFrom$ = "" THEN
                   ' If the user is still on the window they are copying from, then a right
                   ' click will select the icon under the mouse
                   C4_AddIconToSelectedIcons LocalIconId%, 0
                 ENDIF
               END IF
             END IF
             ' If we are here, then the user has clicked on a window
             IF MouseRight% = 1 THEN
               C7_SetMenu 1,"Copy","Paste","Move","Make Dir","Put on Desktop","-----","Rename","Delete"
             END IF                          
           END IF        
           C2_RedrawScreen
           IgnoreInterrupt% = 0 ' Re-enable this interrupt
           EXIT SUB
         END IF    
       END IF
     END IF
   NEXT I%

   'Check if it the user clicked on a desktop icon
   FOR I% = 0 TO 99
     IF IconData%(I%,ICON_ID) = 0 THEN EXIT FOR
     IF MouseY% > IconData%(I%,ICON_Y) AND MouseY% < IconData%(I%,ICON_Y) + IconData%(I%,ICON_H) THEN
       IF MouseX% > IconData%(I%,ICON_X) AND MouseX% < IconData%(I%,ICON_X) + IconData%(I%, ICON_W) THEN
         IF MouseRight% = 1 THEN
           SelectedDesktopIcon%=I%
           C7_SetMenu 2,"Remove from desktop"
         ELSE IF TIMER - DblClk_TimeSinceLastClick% < 500 AND DblClk_LastClickedIndex% = LocalIconId% THEN
           ' This is a double click event
           ' It's this icon
           IF IconData%(I%,ICON_STATUS)=0 THEN
             IconData%(I%,ICON_STATUS)=1
             ' Open Window for this icon
             ' Find next available Window Id
             Wid% = C4_NextAvailableWindowId()            
             WindowData%(Wid%, WIN_ID) = IconData%(I%,ICON_ID)
             WindowData%(Wid%, WIN_X) = IconData%(I%,ICON_X) + 20
             WindowData%(Wid%, WIN_Y) = IconData%(I%,ICON_Y) + 20
             WindowData%(Wid%, WIN_W) = 300 ' Set width
             WindowData%(Wid%, WIN_H) = 200 ' Set height
             WindowData%(Wid%, WIN_TYPE) = 1 ' Folder type
             WindowData%(Wid%, WIN_FIRSTICON) = 0
             WindowData%(Wid%, WIN_SCROLLBARTOP) = 0
             WindowData%(Wid%, WIN_ICONCOUNT) = -1 ' Force Icons to be recalculated
             WindowPaths$(Wid%) = IconName$(I)
             C5_UpdateWindowContents Wid%
             C4_MoveWindowToTop Wid%
             C4_ClearSelectedIcons    ' If there are icons selected on another window - unselect then
           ELSE
             ' Close window for this icon
             C4_CloseWindowWithIconId(IconData%(I%,ICON_ID))
           END IF                
           C2_RedrawScreen
           EXIT FOR
         ENDIF
         DblClk_TimeSinceLastClick = TIMER
       END IF
     END IF  
   NEXT I
 END IF
 IgnoreInterrupt% = 0 ' Re-enable this interrupt
END SUB

SUB C1_DoubleClickEvent winId%, iconId%
 LOCAL STRING filename$

 filename$ = C5_GetItemWinContentsArray(winId%, iconId%)
 IF LEFT$(filename$,1)="D" THEN
   ' This is a directory - so drill into it
   C4_ClearSelectedIcons    ' Moving directories de-selects any selected icons
   WindowPaths$(winId%)=WindowPaths$(winId%) + "\" + MID$(filename$,2)
   C5_UpdateWindowContents winId%    
 ELSE
   ' Logic for double clicking on a file goes here
   IF LCASE$(RIGHT$(filename$,4))=".bas" THEN
     EXECUTE "RUN " + CHR$(34) + WindowPaths$(winId%) + "\" + MID$(filename$,2) + CHR$(34)
   END IF
 END IF  
END SUB

'********************************************************************************************
'                                       MAIN SCREEN GRAPHICS C2_xxxx
'********************************************************************************************
SUB C2_RedrawScreen
 LOCAL INTEGER x%,y%,w%,d%
 PAGE WRITE 1
 CLS BACKGROUND1
 BOX 0,0,MM.HRES,15,1,RGB(BLACK),BACKGROUND2
 TEXT 5,4,"Menu",,,,FOREGROUND1,BACKGROUND2
 TEXT MM.HRES-10,4,"X",,,,FOREGROUND1,BACKGROUND2
 DebugLine$="Mouse:" + STR$(mouseX)+","+STR$(mouseY)+",DX" + STR$(mouseDx)+",DY"+STR$(mouseDy)+",L"+STR$(mouseleft)+ " " +STR$(WindowData(0,WIN_X))+","+STR$(WindowData(0,WIN_Y))+","+STR$(WindowData(0,WIN_W))+","+STR$(WindowData(0,WIN_H))
 TEXT 200,4,STR$(WindowClickedOn%) + " " + DebugLine$ + " " + DebugLine2$,,,,FOREGROUND1,BACKGROUND2
 ' Draw the Icons
 FOR I% = 0 TO 99
   IF IconData%(I%,ICON_ID) = 0 THEN EXIT FOR
   IF LCASE$(RIGHT$(IconName$(I%),7))="rubbish" THEN
       BLIT 320,0,IconData%(I%, ICON_X), IconData%(I%, ICON_Y),32,20,2,&B100
   ELSE
     IF IconData%(I%, ICON_STATUS)=0 THEN ' Closed
       BLIT 0,0,IconData%(I%, ICON_X), IconData%(I%, ICON_Y),32,20,2,&B100
     ELSE  ' Open folder
       BLIT 32,0,IconData%(I%, ICON_X), IconData%(I%, ICON_Y),32,20,2,&B100
     END IF
   END IF
'    BOX IconData%(Id% + 1), IconData%(Id% + 2), IconData%(Id% + 3), IconData%(Id% + 4)
   TEXT IconData%(I%,ICON_X), IconData%(I%, ICON_Y) + IconData%(I%, ICON_H) +4, IconName$(I),,,,FOREGROUND1,BACKGROUND1
 NEXT I
 'Draw the windows
 FOR I% = 99 TO 0 STEP -1
   IF WindowData%(i%,WIN_Id) <> 0 THEN
     C3_DrawWindow I%
   ENDIF
 NEXT I%
 ' Draw the System menu if it's open
 IF SystemMenuOpenState% = 1 THEN
   RBOX 5,15,150,100,3,RGB(BLACK),BACKGROUND2
 END IF  

 C7_DrawMenu
 IF TextInputWindowType% <> 0 THEN
   C6_DrawTextInputWindow
 END IF

 IF GUIMessage$ <> "" THEN
   w% = LEN(GUIMessage$) * 6 ' Width in pixels
   x% = (MM.HRES/2) - (w%/2)
   y% = (MM.VRES/2) - 20
   BOX x%,y%,w% + 10,17,1,RGB(BLACK),RGB(BLACK)    ' Draw the drop shadow
   BOX x%-5,y%-5,w% + 10,17,1,RGB(BLACK),RGB(RED)
   TEXT x%,y%,GUIMessage,,,,FOREGROUND1,RGB(RED)
 ENDIF

 PAGE WRITE 0
 PAGE COPY 1 TO 0,B
END SUB
'********************************************************************************************
'                                       WINDOW GRAPHICS C3_xxxx
'********************************************************************************************
SUB C3_DrawWindow i%
 LOCAL INTEGER wx%,wy%,ww%,wh%
 LOCAL INTEGER contentCursor1%, contentCursor2%
 LOCAL STRING nextfilename$=""
 LOCAL INTEGER fileType%=0 ' 0=Folder 1=File
 LOCAL INTEGER iconX% = 4
 LOCAL INTEGER iconY%
 LOCAL INTEGER iconCount1%, iconCount2%, iconSelected%
 LOCAL INTEGER rowCount1%,rowCount2%
 LOCAL INTEGER drawIcon%=0, distanceToBottomOfWindow%, blitHeight%, fileTypeIconOffset%
 LOCAL FLOAT percentage!

 'WindowData(600) ' Data is saved as id,x,y,w,h,type where type is 1 = DriveFolder
 wx=WindowData(i%,WIN_X):wy=WindowData(i%,WIN_Y):ww=WindowData(i%,WIN_W):wh=WindowData(i%,WIN_H)
 IF i%=0 THEN     ' This is the topmost window so draw a drop shadow
   BOX wx% + 5,wy% + 5,ww%,wh%,1,RGB(Black),RGB(BLACK)
 END IF
 BOX wx%,wy%,ww%,wh%,1,RGB(Black),BACKGROUND3
 BOX wx%,wy%,ww%,13,1,RGB(Black),BACKGROUND2
   
 LINE wx%+1,wy%+15,wx%+ww%-2,wy%+15,1,RGB(WHITE)
 LINE wx%,wy%,wx%+ww%-1,wy%,1,RGB(WHITE)
 LINE wx%,wy%,wx%,wy%+wh%-1,1,RGB(WHITE)
 C8_DrawButton wx% + ww% - 10,wy% + 1,10,"X"
 C8_DrawButton wx%,wy% + 1,30,"BACK"
 TEXT wx% + 40,wy% + 3,WindowPaths$(i%),,,,FOREGROUND1,BACKGROUND2
 ' Draw the folders and files
 nextfilename$=""
 contentCursor1%=0
 contentCursor2%=1
 iconCount1%=0
 rowCount1%=1
 WindowData%(i%,WIN_FIRSTICON)=-1
 ' Do a precount of the icons so that we can scale the scrollbar
 ' This is quite a slow loop - so remember the value in WindowData if we can
 IF WindowData%(i%,WIN_ICONCOUNT=-1) THEN
   DO
     nextFilename$ = C5_GetNextPathWindowContents(i%, contentCursor1%,contentCursor2%)  ' The content cursors are updated on the retrn
     IF nextFilename$ <> "*" AND nextFilename$ <> "\" AND nextFilename$ <> "" THEN
       iconCount1%=iconCount1%+1
     END IF
   LOOP UNTIL nextFilename$=""
   rowCount1% = (iconCount1% * 60)/(ww - 4)  ' The 4 is because the icons start 4 pixels in from the left
   WindowData%(i%,WIN_ICONCOUNT)=rowCount1%
 ELSE
   rowCount1% = WindowData(i%,WIN_ICONCOUNT)
 END IF
 ' The scrollbar top is a percentage of the height of the window
 percentage! = (WindowData%(i%,WIN_SCROLLBARTOP)) / (wh% - 48)

 ' Draw the icons
 contentCursor1%=0
 contentCursor2%=1
 iconX%=4
 iconY%=0
 DO
   nextFilename$ = C5_GetNextPathWindowContents(i%, contentCursor1%,contentCursor2%)  ' The content cursors are updated on the retrn
   IF nextFilename$ = "*" THEN
     fileType% = 1 ' We're on to the files
   END IF
   IF nextFilename$ <> "*" AND nextFilename$ <> "\" AND nextFilename$ <> "" THEN
     ' If we are here,then we have a valid file or folder name
     iconSelected% = 0
     IF i% = 0 THEN ' Selected icons can only be on top window
       iconSelected% = C4_IsIconSelected(iconCount2%)
     END IF
     ' Check that there is room to display it
     IF RIGHT$(nextFilename$,1) = "\" THEN
       nextFilename$ = MID$(nextFilename$,1,LEN(nextFilename$) - 1)
     END IF
     IF iconX% + 60 > ww THEN
       iconX% = 4
       iconY% = IconY% + 50
       rowCount2% = rowCount2% + 1
     END IF        
 
     drawIcon% = 1
     IF rowCount2%<rowCount1%*percentage THEN ' These icons are before the start of the scrollbar
       drawIcon%=0
       iconY% = -50 ' Keep the Y cursor at the top of the window
     END IF
     distanceToBottomOfWindow% = wh% - iconY% - 18
     IF distanceToBottomOfWindow% < 0 THEN
       drawIcon% = 0 ' We are off the bottom of the window, so don't blit the icons on to the screen
     END IF

     IF drawIcon% = 1 THEN
       IF WindowData%(i%, WIN_FIRSTICON)=-1 THEN WindowData%(i%, WIN_FIRSTICON)=iconCount2%
       blitHeight% = 20
       IF distanceToBottomOfWindow% < 20 THEN blitHeight% = distanceToBottomOfWindow%
       IF fileType% = 0 THEN
         IF iconSelected% = 0 THEN
           BLIT 0,0,wx% + iconX% + 4, wy + iconY% + 17,32,blitHeight%,2,&B100
         ELSE
           BLIT 32,0,wx% + iconX% + 4, wy% + iconY% + 17,32,blitHeight%,2,&B100
         END IF
       END IF
       IF fileType% = 1 THEN
         fileTypeIconOffset% = 64    ' Default file type (this number is used to offset the x location we blit from)
         IF LCASE$(RIGHT$(nextFilename$,4)) = ".bas" THEN fileTypeIconOffset% = 128
         IF LCASE$(RIGHT$(nextFilename$,4)) = ".mod" OR LCASE$(RIGHT$(nextFilename$,4)) = ".wav" OR LCASE$(RIGHT$(nextFilename$,4))=".mp3" OR LCASE$(RIGHT$(nextFilename$,5))=".flac" THEN fileTypeIconOffset% = 192
         IF LCASE$(RIGHT$(nextFilename$,4)) = ".png" OR LCASE$(RIGHT$(nextFilename$,4)) = ".bmp" OR LCASE$(RIGHT$(nextFilename$,4))=".jpg" OR LCASE$(RIGHT$(nextFilename$,4))=".gif" THEN fileTypeIconOffset% = 256

         IF iconSelected% = 0 THEN
           BLIT fileTypeIconOffset%,0,wx% + iconX% + 4, wy% + iconY% + 17,32,blitHeight%,2,&B100
         ELSE
           BLIT fileTypeIconOffset% + 32,0,wx% + iconX% + 4, wy% + iconY% + 17,32,blitHeight%,2,&B100
         END IF
       END IF
       IF distanceToBottomOfWindow% > 30 THEN
         TEXT wx% + iconX%,wy% + iconY% + 17 + 20, MID$(nextFilename$,1,8),,,,FOREGROUND1,BACKGROUND3
       END IF
       IF distanceToBottomOfWindow% > 40 AND LEN(nextFilename$)>8 THEN
         TEXT wx% + iconX%,wy% + iconY% + 17 + 30, MID$(nextFilename$,9,8),,,,FOREGROUND1,BACKGROUND3
       END IF
       IF distanceToBottomOfWindow%>50 AND LEN(nextFilename$)>16 THEN
         TEXT wx% + iconX%,wy% + iconY% + 17 + 40, MID$(nextFilename$,17,8),,,,FOREGROUND1,BACKGROUND3
       END IF
     END IF    
     iconX% = iconX% + 60
     iconCount2%=iconCount2% + 1
   END IF
 LOOP UNTIL nextFilename$=""

 ' Do we need to draw a scrollbar
 IF drawIcon% = 0 OR percentage! <> 0 THEN ' We ran out of room for icons so we need a scrollbar
   IF WindowData%(i%,WIN_SCROLLBARTOP) > wh% - 35 THEN WindowData%(i%,WIN_SCROLLBARTOP) = wh% - 35
   BOX wx% + ww% - 10,wy% + 16,10,wh% - 25,1,RGB(BLACK),RGB(WHITE)
   BOX wx% + ww% - 10,wy% + 16 + WindowData%(i%,WIN_SCROLLBARTOP),10,10,1,RGB(BLACK),RGB(BLACK)
 END IF

 ' Draw re-sizing grab handle
 TRIANGLE wx% + ww%,wy% + wh%-10, wx% + ww%,wy% + wh%,wx% + ww% - 10,wy% + wh%,RGB(BLACK),BACKGROUND3
 TRIANGLE wx% + ww%,wy% + wh% - 10, wx% + ww% - 10,wy% + wh%-10,wx% + ww%-10,wy% + wh%,RGB(BLACK),BACKGROUND3

END SUB

SUB C3_SetMessage message$
 GUIMessage=message$
 C2_RedrawScreen
END SUB

SUB PopupMessage message$
 C3_SetMessage message$
 Pause 3000
 C3_SetMessage ""
END SUB

'********************************************************************************************
'                                       WINDOW LOGIC C4_xxxx
'********************************************************************************************

FUNCTION C4_NextAvailableWindowId() AS INTEGER
 LOCAL INTEGER i%
 FOR i% = 0 TO 99
   IF WindowData%(i%,WIN_Id)=0 THEN
     C4_NextAvailableWindowId = i%
     EXIT FOR
   END IF
 NEXT i%
END FUNCTION

'FUNCTION FindWindowWithIconId (iconId!) AS INTEGER
'  STATIC INTEGER LI
'  FOR LI = 0 TO 99
'    IF WindowData(LI,WIN_Id)=iconId THEN
'      FindWindowWithIconId=LI
'      EXIT FOR
'    END IF
'  NEXT LI
'END FUNCTION

SUB C4_ClearSelectedIcons
 ' For many functions - we want to unselect any selected icons (for example, navigating to a new directory)
 MATH SET -1, SelectedIconsInTopWindow%()
END SUB

SUB C4_AddIconToSelectedIcons WindowIconId%, AllowDeselect
 ' We maintain a list in SelectedIconsInTopWindow of all of the folders and files that the
 ' user has selected (by clicking on them).
 ' Changing directory/Window de-selects the icons - so selected icons are only ever on the top window
 LOCAL INTEGER q%, d%
 FOR q% = 0 TO 100
   IF SelectedIconsInTopWindow(q%) = WindowIconId% AND AllowDeselect = 1 THEN
     ' This icon was already selected - so deselect it
     FOR d% = q% TO 99
       SelectedIconsInTopWindow%(d%)=SelectedIconsInTopWindow(d%+1)
     NEXT d%
     EXIT SUB
   END IF
   IF SelectedIconsInTopWindow%(q%) = WindowIconId% OR SelectedIconsInTopWindow%(q%) = -1 THEN
     SelectedIconsInTopWindow%(q%) = WindowIconId%
     EXIT SUB
   END IF
 NEXT Q%
END SUB

SUB C4_CloseWindowWithIconId (iconId%)
 LOCAL INTEGER found%, i%, q%
 found% = 0
 FOR i% = 0 TO 99
   IF found% = 1 THEN ' Move all of the windows up one
     WindowData%(i% - 1,WIN_Id) = WindowData%(i%,WIN_Id)
     WindowData%(i% - 1,WIN_X) = WindowData%(i%,WIN_X)
     WindowData%(i% - 1,WIN_Y) = WindowData%(i%,WIN_Y)
     WindowData%(i% - 1,WIN_W) = WindowData%(i%,WIN_W)
     WindowData%(i% - 1,WIN_H) = WindowData%(i%,WIN_H)
     WindowData%(i% - 1,WIN_TYPE) = WindowData%(i%,WIN_TYPE)
     WindowData%(i% - 1,WIN_FIRSTICON) = WindowData%(i%,WIN_FIRSTICON)
     WindowData%(i% - 1,WIN_SCROLLBARTOP) = WindowData%(i%,WIN_SCROLLBARTOP)
     WindowData%(i% - 1,WIN_ICONCOUNT) = WindowData%(i%,WIN_ICONCOUNT)
     WindowPaths$(i% - 1) = WindowPaths$(i%)
     FOR q% = 0 TO 9
       WindowContents$(i%-1,q%) = WindowContents$(i%,q%)
     NEXT q%
   ELSE IF WindowData%(i%,WIN_Id) = iconId% THEN
     found%=1
   END IF
 NEXT i%  
 ' Update the original icon that opened it
 FOR i%=0 TO 99
   IF IconData%(i%,ICON_ID) = iconId% THEN
     IconData%(i%,ICON_STATUS) = 0 ' Not open
     EXIT FOR
   END IF
 NEXT i%
 C4_ClearSelectedIcons   ' Unselect and selected icons - i.e. no icons are selected
END SUB

SUB C4_MoveWindowToTop index%
 LOCAL INTEGER temporaryData%(9), i%, j%
 LOCAL STRING temporaryPath, temporaryContents(10)

 FOR i% = 0 to 8
   temporaryData%(i%) = windowData%(index%,i)
 NEXT i%
 ' Move everything down one to make room
 FOR i%=index% TO 1 STEP -1
   WindowData%(i%,WIN_Id) = WindowData%(i% - 1,WIN_Id)
   WindowData%(i%,WIN_X) = WindowData%(i% - 1,WIN_X)
   WindowData%(i%,WIN_Y) = WindowData%(i% - 1,WIN_Y)
   WindowData%(i%,WIN_W) = WindowData%(i% - 1,WIN_W)
   WindowData%(i%,WIN_H) = WindowData%(i% - 1,WIN_H)
   WindowData%(i%,WIN_TYPE) = WindowData%(i% - 1,WIN_TYPE)
   WindowData%(i%,WIN_FIRSTICON) = WindowData%(i% - 1,WIN_FIRSTICON)
   WindowData%(i%,WIN_SCROLLBARTOP) = WindowData%(i% - 1,WIN_SCROLLBARTOP)
   WindowData%(i%,WIN_ICONCOUNT) = WindowData%(i% - 1,WIN_ICONCOUNT)
 NEXT i%
 FOR i% = 0 to 8
   WindowData%(0,i%) = temporaryData%(i)
 NEXT i
 'Move the WindowPaths a well
 temporaryPath$ = WindowPaths$(index%)
 FOR i% = 0 TO 9
   temporaryContents$(i%) = WindowContents$(index%,i)
 NEXT i%
 FOR i% = index% to 1 STEP -1
   WindowPaths$(i%) = WindowPaths$(i%-1)
   FOR j% = 0 TO 9
     WindowContents$(i%,j%) = WindowContents$(i% - 1, j)
   NEXT j%
 NEXT i%
 WindowPaths$(0) = temporaryPath$
 FOR i% = 0 TO 9
   WindowContents$(0,i%) = temporaryContents$(i%)
 NEXT i%
END SUB

FUNCTION C4_IsIconSelected(IconId%) AS INTEGER
 LOCAL INTEGER j%
 FOR j%=0 TO 100
   IF SelectedIconsInTopWindow%(j%) = IconId% THEN
     C4_IsIconSelected = 1
     EXIT FUNCTION
   END IF
   IF SelectedIconsInTopWindow%(j%) = -1 THEN
     EXIT FOR
   END IF
 NEXT j%
 C4_IsIconSelected=0
END FUNCTION

'********************************************************************************************
'                                       WINDOW CONTENTS ARRAY C5_xxxx
'********************************************************************************************
' Keeping track of the contents of each Window can get a little complex. Therefore, we use the following arrays
' WindowPaths$(WindowId) - The file path that this window represents
' WindowData(WindowId, Index) - Where Index is as follows (this stores the WIndowx,y, height, width and type)
' CONST WIN_ID=0
' CONST WIN_X=1
' CONST WIN_Y=2
' CONST WIN_W=3
' CONST WIN_H=4
' CONST WIN_TYPE=5    ' Always 1 for the time being to represent a window with files/folders in

SUB C5_UpdateWindowContents windowId%
 LOCAL STRING path$, f$
 LOCAL INTEGER arraySubIndex%, i%
 path$ = WindowPaths$(windowId%)
 CHDIR path$  
 arraySubIndex% = 0
 FOR i% = 0 TO 9
   WindowContents$(windowId%,i%) = ""
 NEXT i%
 f$=DIR$("*",DIR)
 DO WHILE f$ <> ""
   arraysubIndex% = C5_AddToWindowContentsArray(windowId%, arraySubIndex%, "\" + f$)
   f$=DIR$()
 LOOP
 arraySubIndex% = C5_AddToWindowContentsArray(windowId%, arraySubIndex%, "\*") ' Split to show that the rest are files
 
 f$=DIR$("*",FILE)
 DO WHILE f$ <> ""
   arraySubIndex% = C5_AddToWindowContentsArray(windowId%, arraySubIndex%, "\" + f$)
   f$=DIR$()
 LOOP
 WindowData(windowId%, WIN_ICONCOUNT) = -1 ' Forces the icons to be recounted next time the window is drawn
END SUB

FUNCTION C5_GetItemWinContentsArray(winId%, index%) AS STRING
 ' Without data structures, we are storing the sub-directory paths and file paths as strings
 ' in arrays WindowContents(100,10), The first parametr is the Window Id, and because we are limited to
 ' 255 charcters per string, we use up to ten strings (the second index).
 ' Paths are stored with Sub-Directories first, then an * (to seperate sub directories from files) and the
 ' the filenames. All paths are divided by a '\' charcter.
 LOCAL STRING nextfilename$=""
 LOCAL INTEGER contentCursor1%=0, contentCursor2%=1, iconCount%, filetype%
 DO
   nextFilename$ = C5_GetNextPathWindowContents(winId%, contentCursor1%,contentCursor2%)  ' The content cursors are updated on the return
   IF nextFilename$ = "*" THEN
     fileType% = 1 ' We're on to the files
   END IF
   IF nextFilename$ <> "*" AND nextFilename$ <> "\" THEN
     IF iconCount% = index% THEN
       ' This is the icon we are looking for
       IF RIGHT$(nextFilename$,1) = "\" THEN
         nextFilename$=MID$(nextFilename$,1,LEN(nextFilename$)-1)
       END IF  
       IF fileType% = 0 THEN
         C5_GetItemWinContentsArray = "D" + nextFilename$  ' Add the D for directory
       ELSE
         C5_GetItemWinContentsArray = "F" + nextFilename$  ' Add the F for File
       END IF
       EXIT FUNCTION
     ENDIF
     iconCount% = iconCount% + 1
   ENDIF
 LOOP UNTIL nextFilename$=""
END FUNCTION

FUNCTION C5_AddToWindowContentsArray(winId%, index%, value$) AS INTEGER
 LOCAL newIndex% = index%
 IF LEN(WindowContents(winId%,newIndex%)) + LEN(value$) > 254 THEN
   ' The list of folders/files is too long we need to add it to the next line in the array
   newIndex% = newIndex% + 1
   IF newIndex% = 10 THEN C5_AddToWindowContentsArray = 9: EXIT FUNCTION  ' We've run out of space in the storage array, so stop adding to it
 END IF
 WindowContents$(winId%,newIndex%) = WindowContents$(winId%,newIndex%) + value$
 C5_AddToWindowContentsArray = newIndex%
END FUNCTION

FUNCTION C5_GetNextPathWindowContents(windowId%, lastCursor1%, lastCursor2%) AS STRING
 LOCAL STRING a$, b$
 LOCAL INTEGER i%
 C5_GetNextPathWindowContents=""
 ' Check if this is the end of this string and we need to move to the next in the array
 IF LEN(WindowContents$(windowId%, lastCursor1%)) = lastCursor2% - 1 THEN
   lastCursor1% = lastCursor1% + 1
   lastCursor2% = 1
   IF lastCursor1% = 10 THEN
     EXIT FUNCTION ' End of contents array
   END IF
 END IF
 a$ = WindowContents$(windowId%,lastCursor1%)
 b$ = MID$(A$, lastCursor2%)
 IF MID$(b$,1,1) = "*" THEN  ' This is the marker to change from folders to files
   lastCursor2% = lastcursor2% + 1
   C5_GetNextPathWindowContents = "*"
 ELSE
   ' Look Through b$ for the next divider (* between folders and files and \ between each record)
   FOR i%=1 TO LEN(b$)
     IF MID$(b$,i%,1)="\" OR i%=LEN(b$) THEN
       ' This is the next file or folder
       C5_GetNextPathWindowContents=MID$(b$,1,i%)
       lastCursor2%=lastCursor2% + i% ' The position of the next filename - remember passed by ref
       EXIT FOR
     END IF
   NEXT i%
 ENDIF
END FUNCTION

'********************************************************************************************
'                                       TEXT INPUT WINDOW C6_xxxx
'********************************************************************************************
' When we have to ask the user for text input (such as a rename or new directory name) we use the
' Text Input Window

SUB C6_DrawTextInputWindow
 LOCAL INTEGER w%=400      'Width in pixels
 LOCAL INTEGER x%=(MM.HRES/2)-(w%/2)
 LOCAL INTEGER y%=(MM.VRES/2)-20
 BOX x%,y%,w%+10,50,1,RGB(BLACK),RGB(BLACK)    ' Draw the drop shadow
 BOX x% - 5,y% - 5,w% + 10,50,1,RGB(BLACK),BACKGROUND3
 IF TextInputWindowType% = 1 THEN TEXT x%,y%,"Rename directory or file",,,,FOREGROUND1,BACKGROUND3
 IF TextInputWindowType% = 2 THEN TEXT x%,y%,"New directory",,,,FOREGROUND1,BACKGROUND3
 'Draw the inputted text
 BOX x% + 10,y% + 15,w% - 20,12,1,RGB(BLACK),RGB(WHITE)
 TEXT x% + 12,y% + 17,TextInputWindowContents$,,,,RGB(BLACK),RGB(WHITE)  
 C8_DrawButton x% + 10,y% + 30,40,"CANCEL"
 C8_DrawButton x% + w% - 60,y% + 30,40,"OKAY"
END SUB

SUB C6_ProcessTextInputWindow
 LOCAL INTEGER w% = 400      'Width in pixels
 LOCAL INTEGER x% = (MM.HRES/2) - (w%/2)
 LOCAL INTEGER y% = (MM.VRES/2) - 20
 IF (MouseY% > y% + 30 AND MouseY% < y% + 42 AND MouseX% > x% + 10 AND MouseX% < x% + 50) OR EscapePressed% = 1 THEN ' CANCEL Clicked
     TextInputWindowType% = 0
 ENDIF
 IF (MouseY% > y% + 30 AND MouseY% < y% + 42 AND MouseX% > x% + w% - 60 AND MouseX% < x% + w% - 20) OR EnterPressed% = 1 THEN ' OKAY Clicked
   ' Check if the rename or new directory function is going to clash with an existing file or directory name
   LOCAL STRING newFullPath$ = WindowPaths$(0) + "\" + TextInputWindowContents$
   IF TextInputWindowType% = 1 OR TextInputWindowType% = 2 THEN
     IF MM.INFO(EXISTS FILE newFullPath$) OR MM.INFO(EXISTS DIR newFullPath$) THEN
       PopupMessage newFullPath$ + " already exists"
       EXIT SUB
     ENDIF
   ENDIF      
   IF TextInputWindowType% = 1 THEN ' Rename
     RENAME TextInputWindowOriginal$ AS newFullPath$
     C5_UpdateWindowContents 0   ' Make sure to update so we can see the new directory
   ENDIF
   IF TextInputWindowType=2 THEN  ' New Directory
     MKDIR newFullPath$
     C5_UpdateWindowContents 0   ' Make sure to update so we can see the new directory
   ENDIF
   TextInputWindowType% = 0
 ENDIF
 EnterPressed%=0
 EscapePressed%=0
 C2_RedrawScreen
END SUB

SUB C6_OpenTextInputWindowAsRename
 ' Make sure only one icon is selected
 IF SelectedIconsInTopWindow%(0) = -1 OR SelectedIconsInTopWindow%(1) <> -1 THEN EXIT SUB
 LOCAL STRING s$ = C5_GetItemWinContentsArray(0,SelectedIconsInTopWindow%(0))
 TextInputWindowContents$ = MID$(s$,2)
 TextInputWindowOriginal$ = WindowPaths$(0) + "\" + TextInputWindowContents$
 TextInputWindowType%=1 ' Rename directory
END SUB

SUB C6_OpenTextInputWindowAsNewDir
 TextInputWindowContents$="New_Directory"
 TextInputWindowOriginal$=""
 TextInputWindowType%=2 ' Make new directory
END SUB

'********************************************************************************************
'                                       MENU GRAPHICS AND LOGIC C7_xxxx
'********************************************************************************************

SUB C7_SetMenu id%,button1$,button2$,button3$,button4$,button5$,button6$,button7$,button8$
 LOCAL INTEGER itemCount%, menuWidth%, i%
 GUIMenuOptions$(0)=button1$:GUIMenuOptions$(1)=button2$:GUIMenuOptions$(2)=button3$
 GUIMenuOptions$(3)=button4$:GUIMenuOptions$(4)=button5$:GUIMenuOptions$(5)=button6$
 GUIMenuOptions$(6)=button7$:GUIMenuOptions$(7)=button8$
 FOR i% = 0 TO 7
   IF GUIMenuOptions$(i%) <> "" THEN itemCount%=itemCount%+1
   IF LEN(GUIMenuOptions$(i%)) * 6 > menuWidth% THEN menuWidth% = LEN(GUIMenuOptions$(i%))*6
 NEXT i%

 GUIMenuParameters%(MENU_ID) = id%
 GUIMenuParameters%(MENU_X) = MouseX
 GUIMenuParameters%(MENU_Y) = MouseY
 GUIMenuParameters%(MENU_H) = itemCount% * 10
 GUIMenuParameters%(MENU_W) = menuWidth%
END SUB

SUB C7_DrawMenu
 LOCAL INTEGER i%,left%,top%,width%,height%
 IF GUIMenuParameters%(MENU_ID) = 0 THEN EXIT SUB ' There is no menu
 left% = GUIMenuParameters%(MENU_X)
 top% = GUIMenuParameters%(MENU_Y)
 width% = GUIMenuParameters%(MENU_W)
 height% = GUIMenuParameters%(MENU_H)

 BOX left% - 3,top% - 6,60,10,1,RGB(BLACK),RGB(BLACK)   ' Drop Shadow 1
 BOX left% + 2,top% + 2,width% + 6,height% + 6,1,RGB(BLACK),RGB(BLACK)   ' Drop Shadow 2
 BOX left% - 3,top% - 3,width% + 6,height% + 6,1,RGB(BLACK),MENUBACKGROUND1  ' Menu box
 ' Draw menu title
 BOX left% - 8,top% - 12,60,10,1,RGB(BLACK),BACKGROUND2
 TEXT left% - 6,top% - 11,"File Menu",,,,RGB(WHITE),BACKGROUND2

 FOR i% = 0 TO 7
   IF GUIMenuOptions$(i%)<>"" THEN
     IF GUIMenuCurrentItem% <> i% THEN
       TEXT left%, top% + i% * 10, GUIMenuOptions$(i%),,,,MENUFOREGROUND1,MENUBACKGROUND1
     ELSE
       BOX left% - 2,top% + i * 10,width% + 4,10,1,MENUBACKGROUND2,MENUBACKGROUND2
       TEXT left%,top% + i% * 10,GUIMenuOptions$(i%),,,,MENUFOREGROUND1,MENUBACKGROUND2
       LINE left% - 2,top% + i * 10 - 1,left%+width%,top% + i * 10 - 1,1,RGB(BLACK)
       LINE left% - 2,top% + i * 10 + 8,left% + width%,top% + i * 10 + 8,1,RGB(WHITE)      
     END IF
     'Look for special cases where menu items should be disabled
     IF GUIMenuParameters%(MENU_ID) = 1 AND (i% = 1 OR i% = 2) THEN ' Paste or Move option
       IF PathToCopyFrom$ = WindowPaths$(0) OR FilenamesToCopy$(0) = "" THEN     'Source=Dest or No files selected
         TEXT left%,top% + i% * 10,GUIMenuOptions$(i%),,,,RGB(LIGHTGREY),MENUBACKGROUND1
       END IF
     ENDIF    
     IF GUIMenuParameters%(MENU_ID) = 1 AND i% = 4 THEN      ' Link to desktop option
       IF SelectedIconsInTopWindow%(0) = -1 OR SelectedIconsInTopWindow%(1)<>-1 THEN ' Is only enabled if only one file selected
         TEXT left%,top% + i% * 10,GUIMenuOptions$(i%),,,,RGB(LIGHTGREY),MENUBACKGROUND1
       END IF
     ENDIF    
     IF GUIMenuParameters%(MENU_ID) = 1 AND i% = 5 THEN ' Delete option
       IF SelectedIconsInTopWindow%(0) = -1 THEN ' No files selected
         TEXT left%,top% + i% * 10,GUIMenuOptions$(i%),,,,RGB(LIGHTGREY),MENUBACKGROUND1
       END IF
     ENDIF
   END IF
 NEXT i%
END SUB

SUB C7_CloseMenu
 IF GUIMenuParameters%(MENU_ID) <> 0 THEN ' A menu is open - so need to refresh the screen to show it closed
   GUIMenuParameters%(MENU_ID) = 0
   C2_RedrawScreen
 ENDIF
END SUB

SUB C7_SystemMenuOpenClose
 ' This refers to the menu at the top left of the screen
 ' We're not doing anything with it yet
 IF SystemMenuOpenState% = 0 THEN
   SystemMenuOpenState% = 1  'Open
 ELSE
   SystemMenuOpenState% = 0  ' Closed
 END IF
 C2_RedrawScreen  
END SUB

SUB C7_RefreshGUIMenu
 ' Called every pass and during click event
 STATIC INTEGER last%     ' Important that this is STATIC
 C7_UpdateGUIMenuCurrentItem
 IF GUIMenuCurrentItem% <> last% THEN
   last% = GUIMenuCurrentItem%
   C2_RedrawScreen
 END IF
END SUB

SUB C7_UpdateGUIMenuCurrentItem
 ' Called from C7_RefreshGUIMenu
 GUIMenuCurrentItem% = -1  ' Assume no menu option is being hovered over
 IF GUIMenuParameters%(MENU_ID) = 0 THEN ' There is no menu
   EXIT SUB
 END IF
 IF MouseX% < GUIMenuParameters%(MENU_X) OR MouseX% > GUIMenuParameters%(MENU_X) + GUIMenuParameters%(MENU_W) THEN EXIT SUB
 IF MouseY% < GUIMenuParameters%(MENU_Y) OR MouseY% > GUIMenuParameters%(MENU_Y) + GUIMenuParameters%(MENU_H) THEN EXIT SUB
 ' If we are here, then the mouse is hovering somewhere within the menu
 GUIMenuCurrentItem% = (MouseY% - GUIMenuParameters%(MENU_Y) - 5) / 10
END SUB

'********************************************************************************************
'                                       GENERIC GRAPHICS C8_xxxx
'********************************************************************************************

SUB C8_DrawButton x%,y%,w%,contents$
 BOX x%,y%,w%,12,1,RGB(BLACK),RGB(GREY)
 LINE x%,y%,x%,y% + 11,1,RGB(WHITE)
 LINE x%,y%,x% + w% - 1,y%,1,RGB(WHITE)
 TEXT x% + (w% / 2) - (LEN(contents$) * 3),y% + 2,contents$,,,,RGB(WHITE),RGB(GREY)   ' Center text on button
END SUB

'********************************************************************************************
'                                       FILE HANDLING C9_xxxx
'********************************************************************************************

SUB C9_CopyButtonPressed
 LOCAL INTEGER i%
 LOCAL STRING filename$
 ' Clear out any old data
 FOR i%=0 TO 100:FilenamesToCopy(i%)="":Next i%  
 PathToCopyFrom$ = WindowPaths$(0)
 FOR i% = 0 TO 100
   IF SelectedIconsInTopWindow%(i%) = -1 THEN EXIT FOR
   filename$ = C5_GetItemWinContentsArray(0,SelectedIconsInTopWindow%(i%))
   FilenamesToCopy$(i%) = MID$(filename$,2)
 NEXT I%
END SUB

SUB C9_PasteButtonPressed
 LOCAL INTEGER i%
 LOCAL STRING fromFileName$, toFilename$
 IF WindowPaths$(0) = "" THEN EXIT SUB ' Need a window to paste into
 IF WindowPaths$(0) = PathToCopyFrom$ THEN EXIT SUB ' Trying to paste into source folder
 FOR i% = 0 TO 100
   IF FilenamesToCopy$(i%)= "" THEN EXIT FOR      ' End of list
   fromFilename$ = PathToCopyFrom$ + "\" + FilenamesToCopy$(i%)
   IF MM.INFO$(EXISTS FILE fromFilename$) THEN     ' It's a file
     toFilename$ = WindowPaths$(0) + "\" + FilenamesToCopy$(i%)
     COPY fromFilename$ TO toFilename$
   END IF
   IF MM.INFO$(EXISTS DIR fromFilename$) THEN    'It's a folder. Recursively copy all of the folder contents
     C9_RecursiveFolderCopy PathToCopyFrom$, WindowPaths$(0), FilenamesToCopy$(i%)
   END IF
 NEXT i%
 C5_UpdateWindowContents 0  ' Refresh the contents of the top screen to include the new files
 C4_ClearSelectedIcons   ' Unselect and selected icons - i.e. no icons are selected
 C2_RedrawScreen
END SUB

SUB C9_RecursiveFolderCopy fromParent$, toParent$, folderName$
 ' For example to copy A:\Parent\Folder to A:\NewParent\
 ' we would use "A:\Parent", "A:\NewParent", "Folder"
 ' If you're struggling to understand the concept of this call, then the keywords you
 ' want to lookup are "Recursive calls" or "Tree walking". But basically this routine gets called
 ' for every folder in the tree structure below the folder being copied. Importantly, because
 ' the variables are defined as "LOCAL" every time the subroutine is called it gets it's own set
 ' of variables. Therefore, then can be three or four (or more) copies of this subroutine being
 ' used a any one time. As we finish processing each folder, w might dive into a sub folder, or if
 ' there are no more subfolders to process, then we end that copy of this subroutine and step back
 ' up the directory structure. Eventually we will have worked through all of the sub folders and
 ' returned to th orginal top level folder.  
 ' Hint: Each "copy" of this subroutine in memory is called an "instance"
 LOCAL STRING f$, fromFolder$, toFolder$
 LOCAL STRING listOfFolders$(100)
 LOCAL INTEGER CountOfFolders%, i%
 fromFolder$ = fromParent$ + "\" + folderName$
 toFolder$ = toParent$ + "\" + folderName$
 ' Make sure the folder exists at the destintion. If not, then create it
 IF MM.INFO$(EXISTS DIR toFolder$) = 0 THEN
   MKDIR toFolder$
 END IF
 CHDIR fromFolder$  

 ' Get all of the files within this folder and copy them
 f$=DIR$("*",FILE)
 DO WHILE f$ <> ""
   C3_SetMessage "Copying " + toFolder$ + "\" + f$
   COPY fromFolder$ + "\" + f$ TO toFolder$ + "\" + f$
   f$=DIR$()
 LOOP

 ' Get all of the folders in this folder
 ' Note: We have to put them in a local array of strings so that it stays with this "copy"
 ' or "instance" of the Subroutine.
 CountOfFolders% = 0
 f$=DIR$("*",DIR)
 DO WHILE f$ <> ""
   ListOfFolders$(CountOfFolders%)=f$
   CountOfFolders%=CountOfFolders%+1
   f$=DIR$()
 LOOP

 ' This is the recursive bit. For each folder, call this subroutine again and start copying it's
 ' contents to the matching folder in the destination file structure
 FOR i% = 0 TO CountOfFolders - 1
   C9_RecursiveFolderCopy fromFolder$, toFolder$, ListOfFolders$(i%)
 NEXT i%
 C3_SetMessage ""
END SUB

SUB C9_DeleteSelectedFiles
 LOCAL STRING rubbishPath$

 IF MM.INFO(EXISTS DIR "A:\GUI")=0 THEN
   MKDIR "A:\GUI"
 ENDIF
 IF MM.INFO(EXISTS DIR "A:\GUI\RUBBISH")=0 THEN
   MKDIR "A:\GUI\RUBBISH"
 ENDIF

 ' Make a specific folder for this deletion
 rubbishPath$="A:\GUI\RUBBISH\" + DATE$ + " " + MID$(TIME$,1,2) + MID$(TIME$,4,2) + MID$(TIME$,7,2)
 MKDIR rubbishPath$
 C9_CopyButtonPressed   ' FilenamesToCopy() now has the list of files/folders to delete
 C9_MoveSelectedFiles rubbishPath$
END SUB

SUB C9_MoveSelectedFiles destination$
 LOCAL INTEGER i%
 LOCAL STRING fileToMove$
 IF PathToCopyFrom$ = destination$ THEN EXIT SUB   ' The source is the same as the destination
 FOR i% = 0 TO 100
   IF FilenamesTocopy(i%)= "" THEN EXIT FOR ' End of list
   fileToMove$ = PathToCopyFrom + "\" + FilenamesToCopy(i%)

   IF MM.INFO$(EXISTS FILE fileToMove$) THEN   ' It's a top level file. Move it to the destination
     RENAME fileToMove$ AS destination$ + "\" + FilenamesToCopy(i%)
   END IF
   IF MM.INFO$(EXISTS DIR fileToMove$) THEN     'It's a folder. Move it to the destination
     IF MID$(destination$,1,LEN(fileToMove$)) = fileToMove$ THEN EXIT SUB 'destination is sub folder of source
     RENAME fileToMove$ AS destination$ + "\" + FilenamesToCopy$(i%)
   END IF
 NEXT I%
 C5_UpdateWindowContents 0  ' Refresh the contents of the top screen to inlcude the new files
 C4_ClearSelectedIcons   ' Unselect and selected icons - i.e. no icons are selected
 C2_RedrawScreen
END SUB

FUNCTION C9_GetParentPath (path$) AS STRING
 STATIC INTEGER length%,cursor%
 C9_GetParentPath = path$
 length% = LEN(path$)
 FOR cursor% = length% TO 1 STEP -1
   IF MID$(path$,cursor%,1)="\" THEN
     C9_GetParentPath = MID$(path$,1,cursor% - 1)
     EXIT FOR
   END IF
 NEXT cursor%
END FUNCTION

SUB C9_ReadInsertedSDCard
 LOCAL INTEGER i%
 IF MM.INFO$(SDCARD) = SDCardStatus$ THEN EXIT SUB   ' Nothing has changed
 SDCardStatus$ = MM.INFO$(SDCARD)

 ' Clear out any old data
 FOR i% = 0 TO 100
   IconData%(i%,ICON_ID) = 0:IconData%(i%,ICON_X) = 0:IconData%(i%,ICON_Y) = 0:IconData%(i%,ICON_W) = 0
   IconData%(i%,ICON_H) = 0:IconData%(i%,ICON_STATUS)=0:IconName$(i%)=""
 NEXT i%

 IF SDCardStatus$<>"Ready" AND SDCardStatus$<>"Unused" THEN
   SDCardOK% = 0
   C2_RedrawScreen
   EXIT SUB
 END IF
 IF SDCardStatus$ = "Unused" THEN
   ' We need this logic to flip that status bit back to "Ready"
   PAUSE(100)
   PRINT MM.INFO(EXISTS DIR "A:")
 END IF
 ' If we are here, then the SD card is okay
 SDCardOK% = 1
 IF MM.INFO(EXISTS DIR "A:\GUI") = 0 THEN
   MKDIR "A:\GUI"
 ENDIF

 IF MM.INFO(EXISTS FILE "A:\GUI\guidrives.dat") = 0 THEN
   ' There is no config file, so write out the default file
   OPEN "A:\GUI\guidrives.dat" FOR OUTPUT AS #1

   PRINT #1,"A:"
   ' Name, id,x,y,w,h,status
   PRINT #1,1:PRINT #1,10:PRINT #1,20:PRINT #1,32:PRINT #1,20:PRINT #1,0
   PRINT #1,"A:\GUI\Rubbish"
   PRINT #1,2:PRINT #1,10:PRINT #1,80:PRINT #1,32:PRINT #1,20:PRINT #1,0
   CLOSE #1
 END IF

 i%=0
 OPEN "A:\GUI\guidrives.dat" FOR INPUT AS #1
   DO WHILE NOT EOF(#1)
     LINE INPUT #1,IconName$(i%)
     INPUT #1,IconData%(i%,ICON_ID)
     INPUT #1,IconData%(i%,ICON_X)
     INPUT #1,IconData%(i%,ICON_Y)
     INPUT #1,IconData%(i%,ICON_W)
     INPUT #1,IconData%(i%,ICON_H)
     INPUT #1,IconData%(i%,ICON_STATUS)
     IconData%(I%, ICON_STATUS) = 0 ' For the time being when w start the program all windows are closed
'      PRINT IconData(i%,ICON_X)
     i%=i%+1
   LOOP
 CLOSE #1
 
 IF IconData%(i%,ICON_ID) = 0 THEN
   ' If we are here, then something has gone wrong with the file (corrupted or locked)
   ' Revert to default values
   IconData%(0,ICON_ID) = 1:IconData%(0,ICON_X) = 10:IconData%(0,ICON_Y) = 30:IconData%(0,ICON_W) = 32
   IconData%(0,ICON_H) = 20:IconData%(0,ICON_STATUS) = 0:IconName$(0) = "A:"    
 END IF
 C2_RedrawScreen
END SUB

SUB C9_SaveDesktopPaths
 LOCAL INTEGER i%
 OPEN "A:\GUI\guidrives.dat" FOR OUTPUT AS #1
   FOR i%=0 TO 99
     IF IconName$(i%)<>"" THEN
       PRINT #1,IconName$(i%)
       PRINT #1,IconData%(i%,ICON_ID)
       PRINT #1,IconData%(i%,ICON_X)
       PRINT #1,IconData%(i%,ICON_Y)
       PRINT #1,IconData%(i%,ICON_W)
       PRINT #1,IconData%(i%,ICON_H)
       PRINT #1,IconData%(i%,ICON_STATUS)
     END IF
   NEXT i%
 CLOSE #1
END SUB

SUB C9_AddSelectedIconsToDesktop
 ' Currently only allowed to select single item and add it - the code will handle mutliple
 ' items being added, but the desktop may get messy
 IF SelectedIconsInTopWindow%(0) = -1 OR SelectedIconsInTopWindow%(1) <> -1 THEN EXIT SUB
 LOCAL INTEGER nextId% = 0  ' Integers are 64 bit - so no issue with running out
 LOCAL INTEGER lastCursor% = 0 ' Location of last entry in IconData
 LOCAL INTEGER i%, column%, row%
 FOR i%=0 TO 99
   IF IconData%(i%,ICON_ID) >= nextId% THEN nextId% = IconData%(i%,ICON_ID) + 1
   IF IconData%(i%,ICON_ID) <> 0 THEN lastCursor% = i%
 NEXT i%

 FOR i% = 0 TO 99
   IF SelectedIconsInTopWindow%(i%) <> -1 THEN
     lastCursor% = lastCursor% + 1 ' Incrememnt to next location
     IF lastCursor% = 100 THEN EXIT SUB ' Maximum number of desktop icons is 100
     IconName$(lastCursor%) = WindowPaths$(0) + "\" + MID$(C5_GetItemWinContentsArray(0,SelectedIconsInTopWindow(i%)),2)
     IconData(lastCursor,ICON_ID) = nextId%
     column% = ((lastCursor% * 60) + 20) / (MM.VRES - 20)
     row% = lastCursor% - (column% * ((MM.VRES - 20) / 60))
     IconData%(lastCursor%,ICON_X) = 10 + column% * 60
     IconData%(lastCursor%,ICON_Y) = 20 + row%*60
     IconData%(lastCursor%,ICON_W) = 32
     IconData%(lastCursor%,ICON_H) = 20
     IconData%(lastCursor%,ICON_STATUS) = 0
     nextId% = nextId% + 1
   END IF
 NEXT i%
 C9_SaveDesktopPaths
 C2_RedrawScreen
END SUB

SUB C9_RemoveSelectedIconFromDesktop
 FOR I% = SelectedDesktopIcon% TO 98
   ' Move the icon details up the stack to erase the old icon - however - leave the icon position intact
   ' So that we fill in the gap on the screen
   IconName$(I%) = IconName$(I% + 1)    
   IconData(I%, ICON_ID) = IconData%(I% + 1, ICON_ID)
   IconData%(I%, ICON_STATUS) = IconData%(I% + 1, ICON_STATUS)
 NEXT I%
 IconName$(99) = ""
 IconData%(99, ICON_ID) = 0
 IconData%(99, ICON_STATUS) = 0
 C9_SaveDesktopPaths
 C2_RedrawScreen
END SUB

SUB C9_CopyGUIFilesToDisk
 IF MM.INFO(EXISTS DIR "A:\GUI") = 0 THEN
   MKDIR "A:\GUI"
 ENDIF
 IF MM.INFO(EXISTS DIR "A:\GUI\RUBBISH")=0 THEN
   MKDIR "A:\GUI\RUBBISH"
 ENDIF
END SUB
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 367
Posted: 10:00pm 18 Nov 2024
Copy link to clipboard 
Print this post

And icons are stored in a .png file under \img\Icons2.png
 
mclout999
Guru

Joined: 05/07/2020
Location: United States
Posts: 469
Posted: 02:44am 19 Nov 2024
Copy link to clipboard 
Print this post

Well, it could be extended to be GEM for CMM2 if you like.  Add some apps and control panel to customize the look etc.
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 851
Posted: 06:33am 19 Nov 2024
Copy link to clipboard 
Print this post

Oh, very cool, Pete  

This is the sort of thing I've been wanting to see and I love the code format/structure  
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 851
Posted: 06:42am 19 Nov 2024
Copy link to clipboard 
Print this post

  mclout999 said  Well, it could be extended to be GEM for CMM2 if you like.  Add some apps and control panel to customize the look etc.


 
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4212
Posted: 07:05am 19 Nov 2024
Copy link to clipboard 
Print this post

Pete,

Nice work. But I fail to see the relation to the Magnetic Scrolls adventures.

And I would LOVE to play those again. They where amongst my most favourite. I still have somewhere a printed award for "Master Thief" I received for finishing the game (together with a friend, we played 1 evening every 2 weeks in a time where no walkthrough's existed). So you had to find out everything yourself. No Help....
For one of the adventures I even wrote a maze solver, after (try and error) I understood the maze generation algorithm in the game.

The Pawn, Fish, Guild of Thieves, played them all....

Volhout
Edited 2024-11-19 17:07 by Volhout
PicomiteVGA PETSCII ROBOTS
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4026
Posted: 09:55am 19 Nov 2024
Copy link to clipboard 
Print this post

That's a very nice graphical shell Pete.

   

Tom
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3148
Posted: 02:57pm 19 Nov 2024
Copy link to clipboard 
Print this post

What a terrific piece of code, Pete. Congratulations.
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 367
Posted: 03:56pm 19 Nov 2024
Copy link to clipboard 
Print this post

Thank you all for the kind words. It was a lot fun to play with.
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 851
Posted: 03:56pm 19 Nov 2024
Copy link to clipboard 
Print this post

  Quote  ' Integers are 64 bit - so no issue with running out


   
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 367
Posted: 04:04pm 19 Nov 2024
Copy link to clipboard 
Print this post

  mclout999 said  Well, it could be extended to be GEM for CMM2 if you like.  Add some apps and control panel to customize the look etc.


Yes - I did think that it would be useful as a "Programmers toolkit" with RGB sliders to show the various colours, a Binary/Hex calculator, sprite editor and maybe even a text editor (with tabs for different files). I imagined the add-ons could be written in #INCLUDE files, and call a common API for windows, buttons etc.  

But I'm not pushed about turning it into a productivity suite (Word processing and spreadsheets) as there are already incredibly capable systems out there (although if anyone wants to do it as an exercise - be my guest).

All around it was just a bit of fun - but I am very happy with the way it turned out.
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 367
Posted: 04:14pm 19 Nov 2024
Copy link to clipboard 
Print this post

  Volhout said  Pete,

Nice work. But I fail to see the relation to the Magnetic Scrolls adventures.

Volhout


I played on the Amiga - so it might have been different on other versions. But the graphics were on a sliding window that could be dragged up and down over the text (it seems so trivial now - but I remember being wowed at the time). At the bottom of this overlay window were four buttons which opened drop down menus.

That was the genesis of this whole project.

I was thinking it would be nice to add a lot more as well, such as an auto-drawing map and roving characters who would be overlayed on the background images.



Edited 2024-11-20 02:18 by PeteCotton
 
mclout999
Guru

Joined: 05/07/2020
Location: United States
Posts: 469
Posted: 01:20pm 20 Nov 2024
Copy link to clipboard 
Print this post

For sh*ts and giggles, it might be fun to see someone start a different project called CMM2 BOB.  I mean, Microsoft thought that was the next logical step in GUI. development.  I like the GEM CMM2 myself but Then I guess I'm just anachronistic and too inflexible to see the wonders of BOB! (I still have a boxed copy around here, isn't that sad)
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6756
Posted: 01:55pm 20 Nov 2024
Copy link to clipboard 
Print this post

Not PicoBOB?  :)
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 367
Posted: 04:24pm 20 Nov 2024
Copy link to clipboard 
Print this post

  mclout999 said  For sh*ts and giggles, it might be fun to see someone start a different project called CMM2 BOB.  I mean, Microsoft thought that was the next logical step in GUI. development.  I like the GEM CMM2 myself but Then I guess I'm just anachronistic and too inflexible to see the wonders of BOB! (I still have a boxed copy around here, isn't that sad)


Wow! I'd forgotten all about BOB (had to google).

https://en.wikipedia.org/wiki/Microsoft_Bob

That'd be a cool project for someone to do. Part of my thinking for the GUI was to make the machine more accessible for first time users (running games etc.). It's the basics of building a drug empire. Get them hooked on the product (games), then introduce to them to the really fun stuff (programming).
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6756
Posted: 05:00pm 20 Nov 2024
Copy link to clipboard 
Print this post

You know, something like the BOB concept could even work on a Pico. If background screens, icons etc. were held in a flash slot and pulled out when needed it wouldn't hit the RAM too hard as the big stuff would be simple graphics loading, I suppose that could be direct to the framebuffer? The mouse would be on a layer. The BOB routines could be in the Library to make it easy to call from anywhere.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 851
Posted: 05:55pm 20 Nov 2024
Copy link to clipboard 
Print this post

Hey Pete, how did you capture that video of the CMM2?
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 367
Posted: 08:13pm 20 Nov 2024
Copy link to clipboard 
Print this post

  PhenixRising said  Hey Pete, how did you capture that video of the CMM2?


With these two doo-hickeys.

A VGA to HDMI connector to convert the VGA out to HDMI.
https://www.amazon.ca/gp/product/B083K83NNX/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

An HDMI capture card. I just used Windows Camera app to record the incoming video (if you open Windows Camera app - it sees the capture card as a web cam).
https://www.amazon.ca/gp/product/B0CLNZ8267/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&th=1

The whole setup works well, because I can also pass through the HDMI to my HDMI splitter box (not required to record the video). This gives me the options of how to use the output: video out from the CMM2 to a Window on my PC (via Camera app) or straight through to my secondary monitor - or both. Or use the secondary monitor for my PC (usually), my Mac (boo-hiss -  I have to have one to compile iPhone projects), or whatever Raspberry Pi I am mucking about with.
https://www.amazon.ca/gp/product/B071G4NXNH/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1


Please forgive the incredibly messy desk - but as you can see, the CMM2 is feeding through to the 24" secondary screen, and if I'm feeling particularly blind it's also displaying in a window on my 55" PC monitor. Interestingly, the Webcam input (from the capture card) reacts to mode changes much faster than the 24" monitor (it is an old monitor > 10 years). If I change mode, my monitor blanks for a few seconds before locking onto the new display mode. Modern monitors are probably much faster at picking up the new signal.


Edited 2024-11-21 06:17 by PeteCotton
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 851
Posted: 09:09pm 20 Nov 2024
Copy link to clipboard 
Print this post

If yer desk was tidy... I wouldn't trust/respect ya  
 
     Page 1 of 2    
Print this page
© JAQ Software 2024