From 421835ce6637775f93eca276371a00fe90a7c9ed Mon Sep 17 00:00:00 2001 From: Quinn Dunki Date: Fri, 2 Jan 2015 16:01:38 -0800 Subject: [PATCH] Polish & Docs - Removed &NRML and &IVER (not needed) - WeeGUI's memory pages are now reserved in ProDOS's page allocation scheme, to protect us from file operations and such - Renamed various files to be more friendly - Cleaned up the disk image - First draft of documentation --- .gitignore | 3 +- Documentation.md | 776 +++++ Makefile | 14 +- ReadMe.md | 1 + V2Make.scpt | Bin 4030 -> 4028 bytes WeeGUI.xcodeproj/project.pbxproj | 8 +- WeeGUI_MLI.s | 3 +- applesoft.s | 26 - guidemo.s => asmdemo.s | 5 +- memory.s | 1 + guidemo.dsk => weegui.dsk | Bin 143360 -> 143360 bytes weegui.lst | 4904 ++++++++++++++++++++++++++++++ gui.s => weegui.s | 34 +- 13 files changed, 5729 insertions(+), 46 deletions(-) create mode 100644 Documentation.md rename guidemo.s => asmdemo.s (96%) rename guidemo.dsk => weegui.dsk (85%) create mode 100644 weegui.lst rename gui.s => weegui.s (77%) diff --git a/.gitignore b/.gitignore index e353fc7..4f6bb84 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ /guidemo /guidemo.o .DS_Store -mouse.lst \ No newline at end of file +mouse.lst +asmdemo.lst \ No newline at end of file diff --git a/Documentation.md b/Documentation.md new file mode 100644 index 0000000..5b5c046 --- /dev/null +++ b/Documentation.md @@ -0,0 +1,776 @@ +WeeGUI +====== + +WeeGUI is a lightweight library for creating graphical user interfaces in 80 column text mode on the Apple IIe Enhanced and Apple IIc family of computers. It supports both keyboard and mouse controls for your interface. It is designed to take minimal RAM (less than 6k), and can be used from assembly language or Applesoft BASIC programs under ProDOS. WeeGUI installs itself at the top of memory, using an area normally vacant in most BASIC and assembly programs. + +You can use WeeGUI as a full-blown user interface system, or as a simple drawing library for ASCII art. Use as much or as little of its features as you wish. WeeGUI tries not to enforce any particular structure or use-case on your program. It is intended to be so easy to use that you'll choose it over rolling your own menuing system for whatever application you're building. + +
+ + +Demo +---- + +For a quick demo of what WeeGUI can do, install the disk image *weegui.dsk* in your emulator, or make a floppy disk from it and boot your real Apple II. On the disk, you'll find the WeeGUI library itself, an Applesoft demo program, and an assembly language demo program. Boot the disk, then try the following commands: + + ]-basicdemo + +...for BASIC, or... + + ]-asmdemo + +... for assembly language. + +You can navigate these demos using Tab and Return, or using your mouse. Mouse support works in the Virtual II emulator just fine (assuming you have a mouse card assigned to one of the slots). If you have a physical Apple II, you can use either a standard Apple IIc mouse, or an Apple IIe mouse with a mouse card in any slot. The Apple IIgs mouse is not officially supported at the moment. + +If you prefer to learn by example, the source code of these two example programs can be found in Appendix B of this document. + +
+ +Installation +------------ + + +####Applesoft + +Place the WeeGUI library in the same ProDOS folder as your program. Then, at the top of your program, simply load it into memory as follows: + + 1 PRINT CHR$ (4)"BRUN WEEGUI" + +That's it! WeeGUI will load itself at address $7E00 of main memory, just below ProDOS. + + +####Assembly Language + +When using assembly language, you can install WeeGUI by loading the *WEEGUI* library into memory from your program. The simplest way to do this is to invoke BRUN using the Applesoft input buffer, like this: + + ldx #0 + ldy #0 + @0: lda bloadCmdLine,x + beq @1 + sta $0200,y + inx + iny + bra @0 + @1: jsr $be03 + + bloadCmdLine: + .byte "BRUN WEEGUI",$8d,0 + + +If you load the library some other way, make sure you load it at $7E00, and perform a JSR to that address in order to prepare the library for use. + +You also need to include the file *WeeGUI_MLI.s* in your program. This is the WeeGUI Machine Language Interface, and it provides all the constants, entry points, etc that you'll need for WeeGUI. + + +With either language, WeeGUI protects itself using ProDOS's memory page reservation scheme. This prevents it from being overwritten by ProDOS file operations, or Applesoft BASIC. + + +
+ + +Calling WeeGUI +-------------- + +###Applesoft + +WeeGUI is accessed from Applesoft through ampersand extensions. For example, the DESK command clears the screen and draws a desktop background: + + 10 &DESK + +If the call requires parameters, you can make a C-style function call. For example, to select view #6, you would call: + + 10 &SEL(6) + +The exact name of each API call is specified in the Applesoft portion of the API documentation below. + +Also note that you can call WeeGUI interactively from the Applesoft prompt. No line numbers required! This is a great way to experiment with the API calls. Some calls may leave the cursor in an odd location, but you can still get the gist of things. + + + +###Assembly Language + +From assembly, a Machine Language Interface is provided, similar to ProDOS. WeeGUI is called by setting a function name in the X register, and calling the WeeGUI entry point. For example: + + main: + ldx #WGDesktop + jsr WeeGUI + +The value of *WGDesktop* is provided to your program by the *WeeGUI_MLI.s* file. Be sure to include this file in your assembly language project. If a call requires parameters, these will be passed in a couple of ways, as shown below. + +#####Register Passing: + +Simple calls may use a register or two for parameters. For example, the call to select a view uses the accumulator (as specified in the API documentation): + + lda #6 ; This is our parameter + ldx #WGSelectView ; Followed by a typical WeeGUI call + jsr WeeGUI + + +#####Zero Page Passing: + +For more complex calls, there are 4 reserved parameter-passing locations in the zeropage. These are named PARAM0-PARAM3, and are specified in *WeeGUI_MLI.s*. These locations are unused by Applesoft or ProDOS. You can use them in your own programs, so long as they aren't disrupted while inside a WeeGUI call. + +For example, the call to create a view uses the zero page to pass a pointer (as specified in the API documentation): + + lda #addr + sta PARAM1 + ldx #WGCreateView ; Now we can make our typical WeeGUI call + jsr WeeGUI + + + +
+ +Program Structure for WeeGUI +---------------------------- + +Graphical user interfaces generally have a concept of a *run loop*. This is important because the program flow is driven by the user's actions, rather than command-line programs, which enforce flow with specific moments of waiting for input. Most GUI libraries impose this run loop structure on your program. WeeGUI does not. Rather, it provides tools for you to set up a run loop if you wish, or you may simply call into WeeGUI in whatever way is most useful for your program. However, for a proper structured GUI program design, you should build a run loop using the techniques described below. + + +###Assembly Language + +A typical assembly language run loop simply waits for keypresses and responds to them. + + runLoop: + lda $C000 + bpl runLoop + sta $C010 + + ; Respond to keys as needed + + jmp runLoop + +If you want to support the mouse, WeeGUI can help. You need to add one piece to your run loop: + + runLoop: + ldx #WGPendingViewAction + jsr WeeGUI + + lda $C000 + bpl runLoop + sta $C010 + + ; Respond to keys as needed + + jmp runLoop + +Note the call to *WGPendingViewAction* on each pass through the loop. For the mouse, WeeGUI will make note of actions taken by the user. It is up to your program to poll *WGPendingViewAction* to allow WeeGUI to handle these events. When you create a GUI element, you provide a pointer into your program. WeeGUI will perform a JSR to this pointer when the user clicks on your GUI element. + +Most WeeGUI calls from assembly language will clobber the BASL and BASH values in the zeropage (typically used by text rendering in Applesoft and other programs). Unless otherwise noted, all registers except parameters passed in can be assumed to be preserved by all API calls. + +The API documentation below indicates which registers and/or PARAM locations are used for parameter passing, and what the value of the X register should be (in terms of constants supplied by *WeeGUI_MLI.s*) + + +###Applesoft + +Normally, Applesoft is not intended to be used in a run-loop-style of programming. It is a simple procedural language with basic branches and such. To use a run-loop, there needs to be a non-blocking form of user-input. WeeGUI provides this for you with the &GET function. Calling &GET will retrieve keyboard input if any is pending, and store it in the variable you provide. If no keypresses are pending, execution proceeds to the next line. + +Similarly to the Assembly Language run loop, your program also needs to allow WeeGUI to process mouse events that the user is creating outside your program's control. This is done with the &PDACT (pending command) function. When you create GUI elements, you provide WeeGUI with a line number to be GOSUBed to when that element is clicked on. WeeGUI will GOSUB to that routine for you as needed. + +Here's a sample Applesoft run loop using these techniques: + + 1 PRINT CHR$ (4)"brun gui" + 70 REM Run Loop + 80 &PDACT + 85 &GET (A$) + 90 IF A$ = "q" THEN END + 100 GOTO 80 + + +Callbacks +--------- + +User interface elements (such as buttons and checkboxes) can have an *action callback* attached to them. This is a piece of your code that is called by WeeGUI any time that interface element needs to take action. This may occur when the user clicks with the mouse, or when they hit a hotkey on the keyboard, for example. + +In Applesoft, callbacks are simply a line-number. WeeGUI will perform a GOSUB to the line number you provide, and expects it to end with a RETURN. + +In assembly language, callbacks are a 16-bit address (a function pointer, of sorts) that you provide. WeeGUI will perform a JSR to the address you provide, and it is expected that your callback will end with an RTS. 16-bit pointers are always provided with the least significant byte first, just like any other 16-bit value on the Apple II. + + +Mouse Control +------------- + +If you wish to use the mouse with your WeeGUI program, you'll need to take some extra steps. The mouse is enabled and disabled using calls to WeeGUI. Once enabled, the mouse is processed automatically for you (including rendering the pointer as needed). When the user clicks on an interactive GUI element, WeeGUI will invoke a callback in your program. For assembly language, this will be a function pointer to which a JSR is performed. Make sure to end this callback with an RTS! For Applesoft, you provide a line number as the callback. WeeGUI will perform a GOSUB to this line number in response to the mouse event. Make sure to end this subroutine with a RETURN! + +As explained above, these callbacks are performed (if needed) when you invoke WGPendingViewAction from assembly language, or &PDACT from Applesoft. Make sure to make this call frequently inside your run loop. + +Here's sample code for setting up a button that can be clicked, and providing the callback for that button, in both languages. + + +####Assembly Language + + ; Create the button. This is done by passing a pointer to a parameter block + lda #MyButton + sta PARAM1 + ldx #WGCreateButton + jsr WeeGUI + + ... + + myCallback: + ; Do stuff when button is clicked + rts + + + ... + + MyButton: + .byte 2,35,10,15 ; Position and size of button + .addr myCallback ; Pointer to callback when clicked + .addr MyTitle ; Pointer to null-terminated title + + MyTitle: + .byte "Okay",0 + + +####Applesoft + + REM Create Button with give position and size. + REM Note line-number (1000) provided for callback + 40 &BUTTN(2,35,10,15,1000,"Okay") + + ... + + 1000 PRINT "Button Clicked" + 1010 RETURN + + + +Character Types +--------------- + +A quick note on use of characters and strings in WeeGUI. The Apple II ROM tends to want the high bit set when otherwise-normal ASCII character values are provided. Similarly, characters given to programs by the ROM often have the high bit set. WeeGUI refers to this as the "Apple" format for characters. Normal "ASCII" format refers to characters whereby the high bit is not used in this artificial fashion. If not specified, you can assume WeeGUI expects normal ASCII characters. + + +Views +----- + +The basic "unit" of WeeGUI operations is the *View*. Your program can have up to 16 views at one time, and views are identified with a 4-bit ID number. Buttons and checkboxes are also views, and require their own view ID. So, for example, if you have four buttons, you have room for twelve other views of any type. + +A View in a rectangle inside which content is displayed. Content exists in a special coordinate system local to the view it is displayed in. This content can be larger than the view is onscreen. When drawn, content is clipped to the edges of the view. Content can also be scrolled in any direction, thus creating a larger virtual space that view shows a small piece of any one time. + +Many API calls rely on the concept of a "selected" view. One view at a time can be "selected", and subsequent view-related operations will apply to that view. There is no visual effect to "selecting" a view. It's simply a way to tell WeeGUI which view you are currently interested in. + + +Cursors +------- + +WeeGUI has multiple cursors. There is always a global cursor, which maps to the Apple II's normal cursor. You will very rarely need to know or use this cursor. Each View also has its own local cursor, which moves in that View's coordinate space. These local view cursors are independent of each other, and are the ones you will use for most operations. + + +Focus +----- + +In order to support keyboard control of GUIs, WeeGUI includes the concept of "view focus". The currently "focused" view will be visibly highlighted in some way to the user, and taking "action" will affect the currently selected view. It's up to your program to provide a way to shift focus (such as with the Tab key). Your program also specifies when the currently focused view should take action (usually via Return, Space, or similar keypress). + +There is also a construct called the *focus chain*. This is an implied list of views which can become the focused one. Any time you request the "next" or "previous" focus view, WeeGUI finds the next (or previous) view in the chain which is eligible for focus. This focus chain is created in the order you create your views. Views that cannot receive focus are automatically left out of the chain. As you add and remove views, WeeGUI tracks the focus chain for you. + +Focusing is not relevant to mouse control, since the user can take action on any view at any time. + + + +WeeGUI API Reference +==================== + +The following is a complete list of the Application Program Interface calls you can make. Both languages are shown when available, but not all API calls have an Applesoft version. The Applesoft API is more streamlined, and intended for simpler use cases. + +For assembly, each call indicates which registers and/or PARAM locations are used for parameter passing, and what the value of the X register should be (in terms of constants supplied by *WeeGUI_MLI.s*) + +Applesoft calls are sometimes shown over multiple lines for clarity, but of course they need to be all on one line in practice. + + + +View Routines +------------- + +These routines are used for creating, modifying, and working with views. + + +####WGCreateView +Creates a new WeeGUI view. Up to 16 are allowed in one program. If a view is created with the same ID as a previous view, the previous view is destroyed. Views are not shown when created. Rendering a view you've created is done separately. + +
AssemblyApplesoft
+X:		WGCreateView
+PARAM0: Pointer to configuration block (LSB)
+PARAM1:	Pointer to configuration block (MSB)
+
+Configuration block consists of eight bytes:
+	0:	View ID (0-15)
+	1:	Style (0 for plain, 1 for fancy)
+	2:	Left edge of view
+	3:	Top edge of view
+	4:	Visible width of view
+	5:	Visible height of view
+	6:	Width of view's content
+	7:	Height of view's content
+
+&WINDW(	View ID,
+		Style (0 for plain, 1 for fancy),
+		Left edge,
+		Top edge,
+		Content width,
+		Content height)
+
+ + +####WGCreateCheckbox +Creates a new WeeGUI checkbox view. This is a specialized version of WGCreateView, and its parameters are similar. + +
AssemblyApplesoft
+X:		WGCreateCheckbox
+PARAM0: Pointer to configuration block (LSB)
+PARAM1:	Pointer to configuration block (MSB)
+
+Configuration block consists of five bytes:
+	0:	View ID (0-15)
+	1:	X position of checkbox
+	2:	Y position of checkbox
+	3: 	Pointer to null-terminated string label (LSB)
+	4:	Pointer to null-terminated string label (MSB)
+
+&CHKBX(	View ID,
+		X position,
+		Y position,
+		"Label")
+
+ + +####WGCreateButton +Creates a new WeeGUI button view. This is a specialized version of WGCreateView, and its parameters are similar. + +
AssemblyApplesoft
+X:		WGCreateButton
+PARAM0: Pointer to configuration block (LSB)
+PARAM1:	Pointer to configuration block (MSB)
+
+Configuration block consists of eight bytes:
+	0:	View ID (0-15)
+	1:	Left edge of button
+	2:	Top edge of button
+	3:	Width of button
+	4:	Pointer to click callback (LSB)
+	5:	Pointer to click callback (MSB)
+	6:	Pointer to null-terminated string label (LSB)
+	7:	Pointer to null-terminated string label (MSB)
+
+&BUTTN(	View ID,
+		Left edge,
+		Top edge,
+		Width,
+		Line number for click callback,
+		"Label")
+
+ + +####WGSelectView +Selects a view. Subsequent view-related operations will apply to this view. Does not affect visual appearance of view. + +
AssemblyApplesoft
+X:		WGSelectView
+A:		View ID
+
+&SEL(View ID)
+
+ + +####WGPendingViewAction +Processes any pending view actions that the user has initiated with the mouse. This should be called once each time through your run loop. If no mouse actions are pending, this call will do nothing, and quietly return to your program. + +
AssemblyApplesoft
+X:		WGPendingViewAction
+
+&PDACT
+
+ + +####WGPendingView +Returns the currently pending view, if any. This is a way to peek into the state of the mouse event system, to see if the user is trying to do something with the mouse. Most programs shouldn't need this. + +
AssemblyApplesoft
+X:		WGPendingView
+
+Returns in A:		View ID
+
+Not available +
+ + +####WGViewFocus +Focus is shifted to the currently selected view. This will highlight the view visually, as needed. + +
AssemblyApplesoft
+X:		WGViewFocus
+
+&FOC
+
+ + +####WGViewUnfocus +The currently focused view becomes unfocused. Views are redrawn as needed. + +
AssemblyApplesoft
+X:		WGViewUnfocus
+
+Not available +
+ + +####WGViewFocusNext +Focus is shifted to the next view in the focus chain, wrapping around to the first one if needed. + +
AssemblyApplesoft
+X:		WGViewFocusNext
+
+&FOCN
+
+ + +####WGViewFocusPrev +Focus is shifted to the previous view in the focus chain, wrapping around to the last one if needed. + +
AssemblyApplesoft
+X:		WGViewFocusPrev
+
+&FOCP
+
+ + +####WGViewFocusAction +Action is taken on the currently focused view. If the view is a checkbox, that checkbox will be toggled. If the view is a button, the button will be clicked. Any callback attached to the view will be invoked. + +
AssemblyApplesoft
+X:		WGViewFocusAction
+
+&ACT
+
+ + +####WGPaintView +Draws (or redraws) the currently selected view. + +
AssemblyApplesoft
+X:		WGPaintView
+
+&PNT
+
+ + +####WGViewPaintAll +Redraws all views. This is useful if the screen becomes corrupted, or you need to erase it for any reason. + +
AssemblyApplesoft
+X:		WGViewPaintAll
+
+&PNTA
+
+ + +####WGViewSetTitle +Changes the title of the selected view. Titles are only visible in the "fancy" style of view border. + +
AssemblyApplesoft
+X:		WGViewSetTitle
+PARAM0: Pointer to null-terminated string (LSB)
+PARAM1:	Pointer to null-terminated string (MSB)
+
+&TITLE("title")
+
+ + +####WGViewSetAction +Changes the action callback of the selected view. + +
AssemblyApplesoft
+X:		WGViewSetAction
+PARAM0: Function pointer (LSB)
+PARAM1:	Function pointer (MSB)
+
+&STACT(line number)
+
+ + +####WGViewFromPoint +Returns the innermost view that contains the given point. For fancy views, the upper nybble of the result indicates which window feature was found: +0000 : Content region +0001 : Scroll arrow up +0010 : Scroll arrow down +0011 : Scroll arrow left +0100 : Scroll arrow right + +
AssemblyApplesoft
+X:		WGViewFromPoint
+PARAM0: X position to test
+PARAM1:	Y position to test
+Returns in A:	View ID (or <0 if no match)
+
+Not available +
+ + + + +Cursor Routines +--------------- + +These routines are used for manipulating the various cursors in WeeGUI. + + +####WGSetCursor +Changes the position of the local cursor in the currently selected view. + +
AssemblyApplesoft
+X:		WGSetCursor
+PARAM0: New X position
+PARAM1:	New Y position
+
+&CURSR(x,y)
+
+ + +####WGSetGlobalCursor +Changes the position of the global system cursor. Most programs should not normally need to do this, and it may have unpredictable results on WeeGUI or Applesoft's visual appearance. + +
AssemblyApplesoft
+X:		WGSetGlobalCursor
+PARAM0: New X position
+PARAM1:	New Y position
+
+Not available +
+ + +####WGSyncGlobalCursor +Synchronizes the global system cursor to the currently selected view's local cursor. If you modify the global cursor, you can call this to reset it to where WeeGUI expects it to be. Most programs should not need to use this, and results may be unpredictable. + +
AssemblyApplesoft
+X:		WGSyncGlobalCursor
+
+Not available +
+ + +Scrolling Routines +------------------ + +These routines are used for scrolling view contents and working with scrollable views. + + +####WGScrollX +Scrolls the currently selected view's contents to the specified horizontal position. + +
AssemblyApplesoft
+X:		WGScrollX
+A: 		New X scroll position
+
+Not available +
+ + +####WGScrollY +Scrolls the currently selected view's contents to the specified vertical position. + +
AssemblyApplesoft
+X:		WGScrollY
+A: 		New Y scroll position
+
+Not available +
+ + +####WGScroll +Scrolls the currently selected view's contents to the specified vertical and horizontal position. + +
AssemblyApplesoft
+Not available +
+&SCR(X position, Y position)
+
+ + +####WGScrollByX +Scrolls the currently selected view's contents by a specified delta horizontally (positive or negative). + +
AssemblyApplesoft
+X:		WGScrollByX
+A: 		Offset to apply to X scroll position
+
+Not available +
+ + +####WGScrollByY +Scrolls the currently selected view's contents by a specified delta vertically (positive or negative). + +
AssemblyApplesoft
+X:		WGScrollY
+A: 		Offset to apply to Y scroll position
+
+Not available +
+ + +####WGScrollBy +Scrolls the currently selected view's contents by a specified delta (positive or negative). + +
AssemblyApplesoft
+Not available +
+&SCRBY(X offset, Y offset)
+
+ + + +Drawing Routines +---------------- + +All drawing routines work on the 80-column text screen. Coordinates are 0-79 horizontally, and 0-23 vertically. You can use these drawing routines by themselves for pseudo-graphical rendering in your programs, or in conjunction with higher level calls for creating and using GUI elements. + + +####WGClearScreen +Erases the screen, leaving the cursor at the bottom. + +
AssemblyApplesoft
+X:		WGClearScreen
+
+&HOME
+
+ + +####WGDesktop +Paints a desktop background on the screen. + +
AssemblyApplesoft
+X:		WGDesktop
+
+&FILL(left,top,width,height)
+
+ + +####WGPlot +Plots a single character (in Apple format) + +
AssemblyApplesoft
+X:		WGPlot
+A: 		Character to plot
+
+Note: Character is plotted at the current global cursor position.
+
+&PLOT(x,y,character)
+
+ + +####WGPrint +Prints a string into the current view, at the local cursor position. + +
AssemblyApplesoft
+X:		WGPrint
+PARAM0: Pointer to null-terminated string (LSB)
+PARAM1:	Pointer to null-terminated string (MSB)
+
+&PRINT("string")
+
+ + +####WGStrokeRect +Draws the outline of a rectangle. + +
AssemblyApplesoft
+X:		WGStrokeRect
+PARAM0: Left edge
+PARAM1:	Top edge
+PARAM2: Width
+PARAM3: Height
+
+&DRAW(left,top,width,height)
+
+ + +####WGFillRect +Fills a rectangle with a given character (in Apple format). + +
AssemblyApplesoft
+X:		WGFillRect
+PARAM0: Left edge
+PARAM1:	Top edge
+PARAM2: Width
+PARAM3: Height
+Y: 		Character to fill with
+
+&FILL(left,top,width,height,character)
+
+ + +####WGFancyRect +Draws the outline of decorated GUI-style window. + +
AssemblyApplesoft
+X:		WGFancyRect
+PARAM0: Left edge
+PARAM1:	Top edge
+PARAM2: Width
+PARAM3: Height
+
+Not available +
+ + + +Mouse & Keyboard Routines +------------------------- + +Various useful routines for working with the mouse and keyboard. + + +####WGEnableMouse +Enables the mouse. Call this once at the start of your program to begin using the mouse. Calling this sets up the interrupt mechanisms needed to manage the mouse. If you start the mouse with this call, it's very important to call WGDisableMouse (below) when your program quits. + +
AssemblyApplesoft
+X:		WGEnableMouse
+
+Not available (see WGMouse) +
+ + +####WGDisableMouse +Disables the mouse. Call this when quitting your program, if you called WGEnableMouse. This is very important, as the interrupt mechanisms created for the mouse must be dismantled, otherwise the Apple II will be left in an unsafe state. + +
AssemblyApplesoft
+X:		WGDisableMouse
+
+Not available (see WGMouse) +
+ + +####WGMouse +Enables or disables the mouse. Passing a '1' is equivalent to calling WGEnableMouse (above). Passing a '0' is equivalent to calling WGDisableMouse (above). The same caveats and warnings apply. + +
AssemblyApplesoft
+Not available +
+&MOUSE(enable or disable)
+
+ + +####WGGet +A non-blocking version of Applesoft's GET. This allows you to easily create run-loops for GUI programming in Applesoft. The key read is returned in the Applesoft string variable you specify. If no keypress is pending, the value will be 0. + +
AssemblyApplesoft
+Not available +
+&GET(var)
+
+ + +Appendix A: AUXMEM Branch +========================= + +For those really advanced users who want to get the most out of WeeGUI, there's an experimental branch with some more sophisticated options. Most significantly, almost all of the code in this version lives at the top of AUX memory (the other 64k your IIe/c came with). That means virtually all of main memory (and most of aux memory) is free for your programs to use. The only thing in main memory is a small dispatcher, which lives in everyone's favorite memory hole at $300. Also, this version separates out the mouse code as a separate driver program which can be loaded or not, as needed, saving further memory. If loaded, the mouse driver lives at the top of main memory, just under ProDOS. Interrupt code can not run from aux memory, so this compromise is necessary. + +This branch sacrifices the Applesoft API however, because it is not possible for code running from aux memory to access Applesoft programs and variables, as is required for the API to work. + +The AUXMEM branch is experimental, and not currently supported. If you're interested in using it or playing with it, feel free to clone it and play around. I'm happy to answer questions about it, as well, although I can't necessarily provide full technical support. diff --git a/Makefile b/Makefile index 033531f..57c040f 100644 --- a/Makefile +++ b/Makefile @@ -11,26 +11,26 @@ CL65=cl65 AC=AppleCommander.jar -ADDR=4000 +ADDR=7e00 ADDRDEMO=6000 -PGM=gui -DEMO=guidemo +PGM=weegui +DEMO=asmdemo all: $(DEMO) $(PGM) #all: $(PGM) $(DEMO): @PATH=$(PATH):/usr/local/bin; $(CL65) -t apple2enh --start-addr $(ADDRDEMO) -l$(DEMO).lst $(DEMO).s - java -jar $(AC) -d $(DEMO).dsk $(DEMO) - java -jar $(AC) -p $(DEMO).dsk $(DEMO) BIN 0x$(ADDRDEMO) < $(DEMO) + java -jar $(AC) -d $(PGM).dsk $(DEMO) + java -jar $(AC) -p $(PGM).dsk $(DEMO) BIN 0x$(ADDRDEMO) < $(DEMO) rm -f $(DEMO) rm -f $(DEMO).o $(PGM): @PATH=$(PATH):/usr/local/bin; $(CL65) -t apple2enh --start-addr $(ADDR) -l$(PGM).lst $(PGM).s - java -jar $(AC) -d $(DEMO).dsk $(PGM) - java -jar $(AC) -p $(DEMO).dsk $(PGM) BIN 0x$(ADDR) < $(PGM) + java -jar $(AC) -d $(PGM).dsk $(PGM) + java -jar $(AC) -p $(PGM).dsk $(PGM) BIN 0x$(ADDR) < $(PGM) rm -f $(PGM) rm -f $(PGM).o osascript V2Make.scpt $(PROJECT_DIR) $(DEMO) $(PGM) diff --git a/ReadMe.md b/ReadMe.md index ff5f407..6d802a5 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -15,3 +15,4 @@ To Do: - Make WGFillRect support 1 height and 1 width - If called in inverse mode, clear screen clears inverse +- Fix unclosed PRE tags in documentation diff --git a/V2Make.scpt b/V2Make.scpt index 710ccc1e290d3b05701072c81e2c3fed7f98764b..32c845b094cbf7a990e04c509f870aacbc4061ea 100644 GIT binary patch delta 375 zcmY*UF-yZh7=39gE#!!en>sYmI*4e%RSKpQY|)M?(kjHXwg+jGCMn`#hj#3CoBu&j zx)v8F9i)ScAes6f1Sh{_s(0}2yYJn5@4J`WEcf)C&e;4K$&+enx=0t2iCIRd^0Cn5 zv}nlc?iCV{Sk1I}FL3;hRw?8En%Bdh%1+#yhzI#Fh3wsz2<3c{8Ln${%M7^F^N~dc zm^X|zJyoOn}pT4t;g!C#3tNCFGI!;O2f=8&Mk0xQ6>?{n>rG8`{F$P@PHg)#t zc1~vtN2IMPxQFzNk%|!%n#dF1h0Rx;k^1i@Bn}LD(e&&+Nv$!2tnD1vvPQJ&jY{M0nSyWP*n4=II%^<+Q!N73h zXy5~&enAlX+{r6XfNVwv4veeLmop4LnebSLn1>mgAjw-o#A(Ww*A(f#B zNa`~b0=4Ti1OR#Y3|T!x8brZNcQvV_zPM25H#d1;#TwI{&q zu`Y|SWqX7*m!3jmTvtJa>mZi$PC$T{q&Be)cI1S`7|fak@>+<>$wEk5zweuSuOu6i z=8vBD&odm&_RTjl-^`u)&F>rGyiquB+?}LL{Q3|5{r!7Wbl3IIByjBsT*jR#!#M5| z=fH@TvreBjKR_wB91JpxHmV;nR)o%!ZR2 z-PSs~fp^7H_ehI;nPg$J^dtlen#)r^?MOYp>Za4tTV&hWL1XoT?R1v8B-5QKaV1u_ z6_Qp>*aS75G}B(;g1Qia-&Hpqw%($E#TH1n1&`9sV|4eU{Ekw0da#ow!C!qtA9axv z8|yeMeVN&5Sc=bLz; zls`=BQZ}*vOWc+dVtMLysh_+@Nf#BLU;V_)6C0tXpR3~6qaB6R=<;i`#5czs+{wO0V2?e*)x+FEx)BAAHl8SbDRgqeCq29tWw! zeAEOPy?!&+>{L_^frKA__~5de_D7)4_TfwIZ!eWQad)iqK}&Pi*Xjr|M6I@8XPtEa zUQJ@ZM%4c7pRV6JB(2=DOweZkt;0VRLWkO2Y_yK^bL;i%46K)%%*&^d-eRd2I#LW{ z!#=b%Tf%1?d``b(`n-h&{3|6T&;4dO;W&*!_e9zgnVQsu&x^I=lTv0Ce^RU)KNLRP zYsFKiO@|F+rZ}o&wTsPYL2<;enbTfr6F%d0jjYH1CqTJh3qR7&l;)TzM=Oa8EIFej zcuXu)5@RvpR1$Y$;-$ER{|?MiCgdSr3$`y@`|xZS`y?np8$6(dS#l_8{MiuWM;Ak( z)E}SF_#cliQ4)Lm7i%=Q&Rp!{`#30nd_&-~>Q+BJez_;`Q2Uff!5)2Nj7i`Zy4tR_ z(`!d43d1rU)A<373=u9k-RVxZ1y?TAK8~O1)$P}gQu(WoTn!Ggp~RF^->dFF;%i$L_=|@Q#|@_3msy_rb--xV zM2rDiGr=0&%>w%PEh?Y~37!4Y>VUCb6V}1 zR!1&rw)D^~r|6bGy5%gDw9&z<17_pD$bP?rI#dn%`W~jB7_@>)UA#&xKhKn1xJ9w} z$4w($@}agp)Jv@?w$KUc)`w0~w;|L+-Nw)<>NYvsHIbqGgw^fZ$gp-@Bt=N&N3G@0 ztQU;DWxb%|UtaG7A-B=#Ho&%kV+Sp;3_uMmlh8S86~ZYPXd(&H3}LubCk$1Sd4fwT z@vuzr^MsYt?|vwB5xZ~+x`6hJB(u*K%G!j#IbvmSAkT8ALnmitf0XV{XCEm19HsE- z%S{?l8MLLBra;L1xewEK4^>(^La*3&uIH;=jXjUk_31m0&_RVA>*LxACj|5n>wp$v zJAl*kC;*g`;_j=~y|5i=#Fv`%t`6^vy!o>^uG_mPzhK59uE(2en?3z0E@#8^g$ouG zaO*eB&$9zwyS!oM+*}Ah!?1wkzQ(YS~$OY0xu7tiC^f2>E~;F4*o4S z3vw!0FcZsRre#5xY&l|s3Qn+eOort|68NQ+4!*I{5qytk>G|K6gFrA$!y1P@-Xv67V>rD{zGB+y=D6 z9ddt}ZR6UO=OQ*IENv1{%_@GA5VLiB9haA9Q*_CvOwosG%Hi!0?l#NQ``zh-YyB2Ub@-UOTU{kSVk9_)?a(QmwZ)n zH=%`(d{qNGxMWZZgBpO%7y9GipOuX`Z4HJ9vU)@3d=XQhhK5aTSA^>g8X8G)rsM8h zf4(g;rj8TNI@2MwJ=E_bKlFw;N*?#}d0z3cx_R1AsW|Q!FV@$kyZTF+rLA#`o2V8t z31pCslwmoaGCORNz>g&WktI$Eo8=JhH*b+ZrY&H#1;;kqg8NA1rJW&i-n@IciXC8a z?%pTGs?9yqBcy+u;Bg(Lrz**-m@BL@kjU%FqKPBVpjf(J!q>)I?LmLTcAmnmo1s;N= ziI|0innschCqxfkHb(FlD|bJ;0!IzK+u2AORv4@a;V1b70$BcHrJO?!kR>Y;OIIYs z|2C{hAp40}=Q9^Bxsh0UBcb6&0tpd*2obD!0u8J`=>SPh0~5OS!4QE}zPKVw2Uj0w zY9bg<&_Uy?ZYEZkvV;^kxkN3U7(EnE)BOH)(oM}PdnoyUhWg-w_W>oxY3K|qc^^tn zQF4sJ#)E_4zpmU}z;jJgn@M2}JKp-~~BrUm-2w-_M zW}J^^X#6ggqapjqQ-ZE$A1)hEj!VN5;8=ag48BcBD}lzQwGc3w)8YNNawpf~Jw%Kv z`0JIKj-3r;M-zGB5V7_84LAqeD^l--BR%`8v(#;=Ft0pATP<0Mo6k_e60l&9hItWf z>b)!zx(1o@b=c2Uz_+D--Ei(kO!7`4&K1orNIu5^1VDu$h#V}49MT1hr?Ui{(Eni zHAC>o6>@S~4dF=@Cf+67t>i$)Sk_Kh1N$m&1NWB;-EzopEahJ*<3|#q84e&gMAXp) z^qVgN?%jNe&0>7^dCb1RvH{s1ffOJNm<$GUA<=<}qM*85%y7L}3FBIM8u5=At`RF? zWMEPdgauM$Q(JUyK27=iDpvtVQLpCV-1NZQ^vQE`TArKJ^4vfGb8{N!CK2iiI5nqn zYM4$JeqY<2Fj?_RgIyH2LpaFfnA(tRVQqCX;3Si<`5bQ1IEpTsg_2B{A`{UH!$B%v z15#0SSSEx=gf7rX7Wrj)=sd6?FP8Hg%Y_Vf_CiKv7(loS0O2GJ9L7Qt$|gd-a0S1U zB0T@6SX1H`6rxYK;~1dG8i{1c!L0Vw$X)GxB(ps$GP!+fI9ckC&MG4>K%1oDzjCQF z{TC4UN==-V5DdnFNW23Ah_n?2^tOP(7BJcZrs$Nwa&zn3@Yle8jqKM{R|kjd0DS9o zkWN~2gw_Doysr{R)9Io%{x4-t0tQbi#}Psb`q#x)2gI*+q4i|L_Rug)9+X9M*wD4r zy-MBQBB;^TMN>!lQ@n9vP*K+*Tpe8PI8@_t%Y%X}OSBZ=whJaLT*&?br28rnPQ9;u zVrrdv*q1(H^@eWv$h}_vVLamIYt$2NjH{I22&ieaiv^E(`Pp7_(#OMLINJ*cT#phZ zr_@NV8ab^-&R|4_!A%MbKCHmtOa%u2T7kjG6&QR`fx(|_aLG70vO&hdUv7|buwKEz zqZJ%{pMrxO3JzYS;NU;VIGCGWT`+GBz~F7w`2|k`V1849#k&<){GkGihbgdllmd&# zS`=J7Rl&sz6HQ`~~9SVNpEX zLwA13@UZyHCWC8#tbwI6;)U_t4e%6N{6#b)#lvp}2+S4$KuR|MaCCy`k7QA*KwubK z6atsZ5SUf6$#vwx9|N2#$o0U41Bxy~kr)SoVdx2EXimJpIq>p!YcJ&97?oa`!MMyh#eY?}%)c=%Q%qBd%%2P(GI_3aFqgSRX^wH3 z=}LlenRvrNQk8L;KUWfr%lr=|!MM!-j7!9GnTh^~fQv*fGatszxJ(EcmkA-`GQmU& zmnqvz;WFif!ey!@jLQ@ss89cY#gUKm2Q{xx)oI{b3a3h+dS0CM!FMa21k2+U^o@1+ z{VN+Q+exD5&*0PN7hZ3#uL{ncxa$8{7d$Q>wQvQ!NCDa1s!MMFn~t)jUhipN6+6UW zKlJwbss?t@?*7&m_`EXckAt7bHZlGsIryU-jA47cwuge3;G71iqj5u)IEt4pd$#1~ z&pDSr4@b;r=-ui=Uso&oy1v!BwVyUbC4>70dbjq)d$(46gLmry?R*ElTd$&b>mV~* zeZvvJb1mrIg3@O6ZiQ%P6MDCr;PMj!ioJ=FknG)R0q<5w@ou$j#9Z`lwJ6>#Ip--w z&&NSo4-)lFiofe>>1fxFJhMEDJh`q?*LopswQlWJH+bU`%HCM_k9Br;isx=mUfJx5 zd1WPKFO~hVY)rYkJlP|7M9(qLWlv${4)k~NFP8HE9q-+0QM_9XlpJE-t*2U|-mR8z z@@}=DcdI4l-D(lRyVU}VGUnYsqZwH~;Cyu%7>+8I4Tj=%gOgE=E>nPR^P%`B6A>XsF$AIq99`J>2Je!y$`CyRZmW z`ai|w#?Qg;n+%>DWl`~q2KsGs!EdvVUJFrNJ1{|GI^Vw4Z}VrxZ*zd+N_&Tb-{xq{ zZv$&`klzN7*g&nVOzmL5jWWsLw<(!q1nm5&@0%E-s|-$G`zAPDA;W15BF3jLInJ+RI#5ugTMfsww z@qCd)CT)%JMN%AJ#Kcs-h>0OzRG1&*iw?*0MOO#$MKI1=`JzsRj_X7^?o%JqabmLX z-jW?i80{eBO+t<)Kp1Ufgwao9gwY#> zzgZO}jN>&j*M|ow+>9Rd^ z7?~q>z%%9ulFx8rj#!!GDim#=4c-#_AAVhQo{@z+)8M1WjiJNfH^uqS3R1p(xXhN zLS8TnBXiV=%uy#oD#QXsa718kwW_kU3gh9_j+5@pL)A zMrMv0DP%C_=slS^YDDG;WD_A@WsVwT<|uAKDYI^XnPJQk3vS08i5|pcW6FV4gLV~$isO10xq&Bd4_m_JLjnNDPm;wBAemVLmgbGHSTXs8vJCaeSI+=U?CxvM1e zz=g-dX^ThrKH0Y$M&E8XSW2PgT!LKAoV(FNz@zBgJsflHhA41mV75gbxyjo*cjcx+ z;M}cQ&zHIy52J54B>Q$_W&6Rmt2X5_D9+vZ76He?9I)1+>>6UltmLqh_QFQ3H(b{%e+d*qPX>Av+eUHh7*>5+z56FvqA5d@`edw_Vh2UYGId^4;nAe-}G1KT_FN zoh`po=~d|X1ci=IR_ORNg^hnqVdG~jZ2U9G#^<}3$$%<s@Sg#ZgHVGbjdbVLCNdCyx9l{I7q_`OpC^RNyar~M>o+Vo7}7J z{q3}9dq<>4$QXre^iJkFEX_JRG(N_NVYAU?Nc3y(-Rzf`1Tawq6>JgXBgt}4bCW}zWHHS)u~hGRGo9G>eM+h-CCww+Z?5eB;sxkUq2M58dN{8B5o>)+40Jlsl+!5 z?bGr96s;sCETMBPG%@n~ei@-4@(5yHJc^aj=EcX5N@51avKU9vRuU?rOG*4Pe!h$b z6_+*Y=ZXog9Z@LqiTDNaN|!=e;!;LWRp?wZqSL79#$1XrjZh%ej}jV!jV9uLHYc7S zzENp$MM=zDvMfI*w{QeeT}(s}Z$=PL|7^-QKqIWU;@TIT`ovVgEGh`YG!ijH(xeg0 zOpK`{rj1=7@%;<`(bBE-#4fgzde(^+>3PDft=l3_VRz;^tD+Lh%8eCeJK3GK7k93G z(diJbHF%v?=uttB1h|C(Mz^AcVYeJ)*m4`SEsj@E%YcxFFnXDcJ|)XED^G8BD=MlP zo1>bsx>aG|7N)_`!ng^0HPa3VR-S0EdI;9JZ6{0y?bCb9>$U)p-R{=c?GztYm(SSp z^BLQXr<~sHmv&ZZ+3mJVPGe8G%^_T59agEkIpUPFD&mr}r`#b70MJZw^+NGs$1@1sp^|#XiPAm<$7PDp)m`G5W$j^lHe20lYHA#oEtXM`r4g0IfdscyGY)S# zd_ZUp8wiedR*17Csqq9Ta0XlD*5~bfaYTt#Y?bZBsrs*3t%1__2HE(}B$^(BM@McK)C;*+Ng>ATNO<{G5~>w1 zzeaMek<_j@BTsO4fW1b#xtpYKfD}~du_%-g1yvDOsl8DgX#gyP!OD#{uny-0gS?1T zg%Hha(3BXoD~{T(Z*inX2t#<99s(PH4(1_E25NtZLv3;0gb*7bgeaKlAL86muwoRa z>mC*o?15onybsg%O)!A9gMf4q)efN^lflSnryi!tRw272B({9p7F?~^wgVTH+c+!e zs*c-V)fOd~yp^Dn3L(Cm5n|lYel1z;aOm$)RBVNQF8`RDsCM)?1ZB^5Z$1NP4Z_U8Z-sF{l#4Yu;|!RI z{S6@+?biX*XCQNFgeg#m(D0)D#1vUseU#y`q&Vb&I1p+XiU~_9M zr#Cp`4L*4$6B=)k*YpP8w`6^PyrEg`)Eg?}4H>?hWWV0f;2R<_RK?qghWue}hy;P$ zu?D6Kx|ZGei+-m=tPY67aTdLIfb7uUgO109NGF&^V&GAzTqi|+06|40MNMF;po1mC zFe*9Pg97P-x&az3yPbn%;O8>EKkKO9M58l0ur=opS$T`B{FZF7?+(loCQGPccyCI0 zw@4>o><(-Kjy7>Z;B_%RuvXLtD3H-hV1L8hZHZ$|bmd*rbI%!T@Q@%@AQo6H#9}eu zBf)sTBe9@gfI(}7$2^1&=BxA|AIx9rdDQN_LxM8*Z%L0naA$k-8N4m62kv4+sJ%y8 z`FkER;pMv|>|YA@Y)xG)6sTM`aFZ173=EONO)Huj(f}NRdP8G8J_4zAi&k3$op zybkJQOju(=tkE6m-$m43CLQ|Qb{o5E+gsR_cW>K+i<)h9lnQlf+GDeRk$y-K`MtuW zeC8i^LF4Nt8!wPnszZy;X`7#I@J}Y;B(hYbPs6oLaf0&;l0WBBqJ?C0Hh)&GJmF6w z-5*n5YwIe!JDlAlcY%a?O~$80AWBg3F**kQ4o*ARj~&9*(>wH+sYo5Kq5i4`K6sry zyPduZQ5%EFRc+#V6{X4mLP}QNo?MZAsLB7Rw=ml8;f-f#aQjcK!fhBlH_ z$^>hM)j6o*ZmROV+>pu&6v}Ss`7b?sd|oP1ajb`^uu7*bIDS!4^`HY0M)8^qE1cF` z56KTVSVN~LTo7P#REw7Tg2Y1Lz9gMrk@!mCI!R|2S>uTSjjF050*8j5RVeIcvpM89 zjFxWMqZs*)8~Fu6Fb()AAMleAbka}pfFJJ99N{Ej{{J5)kUo3P+lmx34RE&Zk7$yD({_aFOXC$5HN#EyiFoJ@J^KgzRGOXZJ zD-?thP{;nvq=hUcDGdBD7JuDDg2O+aR@DVdt00!NTxJM3vs;~$gT#mNpi@7ser9l5 z()b=|Sb5TqPx*kfdb1BW_ zFl&8%r5JQ7srmVOsB@h(v$iJT<-SsY6ow!xf`od4gvJ5JlKiCwRAG_HT)KP(Y=NPu zA}*FKGY?6ulnoVM&mypH-(0AO# zoiqWntX309#%6VP6*dwdIS-q(8_?Cl6l>!V(}82AmkyhZ=RKMVT^l#9h%@-F(HVDd z&}?Ew!p7_Lsl@ci+Uqov=uN~0iD9BrZQH1p@-FFR zda#5;cISzcbSh!|+TTy7#sw7OIKXEUfis)L;ChnONMe(`>d*V=szqMS=U3>e41XV; zP?mT~T{X)trunZxBk7c;Dp^E9Isz?YEIg$alBF?1RE18@JlT<+!)%uaEL?a>BcxU6 z5HlkPfc6xLj}Td*OK0NzXv$LN9J1s?iOMt4i}@(V#I*Uorme=6!3Emuz3SRqv{zI6 zt)$ry9D{FS@Q?)ds$pMvHCz`B3WCO$xbYQkj0{MCt+5f-wQ+!k?gZE{8)0D}WxxZQ zS!oQ3)K)t{qiKbkK#~oRzg16sZU(4Y%!0g!PY zBN+Tcw3yC4x72@==AK=Owk&0m;T7`@4Q(-&RYNzc;S~U2qA+SCz?ojWVOE0B)ALi~ z!Yxah(DmJ_yaEjdLCjTtc(l<8JreSl zG;;&EdDTX*#^}`=y}A*xgGI6GcKp>yU#;}jx!vgBvTdx+#%gV>#>T3F57$k<(@DQ$ z@4_OLRcu7(^KEeRqPzKcJH`NCxEdj7$pz4r#qEBE%(`v&NJ*XezO^uC+)z99+kmh}CWwt*~H1RbOY)5BDOpoj?rRUoMf zCyBdnO2mFl*yZjRUmCtOjgoPKvRDm1K(+V))!E=YjX{RR0i_rlP>FGj9!2D$kBy8L zX^o5uS&bpHtxmbudofXHpmOtEXSYnYudGg?p2&ks%BxLET3XLTTS8C)0(CIg3voAm zfGq^m;8%h=yy}E9Er9svuxSdZz%dyK@8yi*KR+VK z+c_Y}ho@c585LrvQ$^j*p!ziSc+XySxC7@^!-i8)|GC(!g~yDFImp-+Lx887dEfoD4Eve>k42wkFk17byrMPjRs8ht8CWe zP9CpTTlzp(B7sI`aRu<{2P-G*Xq|6?75%!e{B(UUq#S@uDzET zY>lABI9n1vQyRKI!*L>})0PCSdcTt9=9&E}nwxJ%Pnj9D&Ev}2Q>6T3rmK3-LVJHE z`ge;JP0EsrMP^iL=78-IT+uPyH^C}*F;uw}s`Oa!b9)c|5Pvb}{qQksAzbI!p zan8KhSdhJfm|L8^jHZhSd$A=KztOvk^Gu7O?8jvhK@8b(#Y_<26=yBRIW%R7g~qk` z5;~uza*5=U#mh=8CB)+;mc=E|{~KIpKTWVDxg}YaT%w`mI6w)au%xJ@5ID4yN}aGE(84!eKB7&p$>sEIco#sVjNnvoj#qDK=T-PaS8oB@aPz}sdK&k; zNPZGKo%=4*r&tcQn+Pvu@Bv^ueM2`YY1f~3J!uCegO7P1o0rY_1&CKQyTFS1ZWsY1 z6<`kx!%EGpIw$}M)hMIxl~ASi)WdDY6V+kT2)gVAHnc+?SZW^AH3&WX z;91)XFJ%?0!2$qh9*h#-%vO9Y|9BSnt0iczcru&7SsE4h$jp@*gpY(b`^L{o) zlWjP`mrSH;#}iG>#BA+D#GhuT6HjS-RmYR1v|lojqa9SW9Ga~ zrU{o*o=E+uNiyJM-8uq;l3z{!=uh+0)6+;F9iKsCrfRpPClp zw(cWc6KtlG^i)C_byn9T?E_fWlMlnPnxt*G2(L-nh$-o5v(px&%}slJPTK5@w2bt$ zc`(kbO(dG6eU>r@CY?&W?y`8ND)zXh^d&3&u0?&1EIXxr5>R9||E0|%nxtKlGCP&% z)S8JVd9UqY}{*%HZuB_63O2~w0D}*vu zt(N~N?P?qRsJC2uj;wKg(Y0XQc{w~Jg(X~>%O6!_y4D|kEHCq3N5^>&4qWiH!2k`8 z`$)kbv~l%4iue_f`Dzu#{Ynn$%rNpH?!Lsf^zTNdkaYhP-i47i8$aF1V-xWlfQv&i zDDHCTtm_R``Yd2#{MRr63wW3HdGfn+)ZRwU&ihZ!4QA&hOJ&cP;s3}BJ-B!#v7fH( z$B!ON%Pw!bpCkrnw0sP|Y)+W$73WtBwC72NY2N^Rc1{1=0#E za?v0cBn7}%;J}?#jMp|)B%Oqpi_mULTI}}{fI#}oMV;PbtlH~`hhs8o&4O#wU^iA6 zYm9DUC7*)YI?+)gkSsoe?(|e_sx=j_#O+jZ5jxqqseNVJ!$Oy*8DHMBQ42AK(k6Jk zn~K}v9S`4?&?~Bej*__rRpvN+HicwqtG6}StVokBEo6SS{Q)Y0+xkAGj0h4cpc+|m zvNQp*ECd-V(~V2eD@zggKJ9Qg5;nHcTr1s^V(_$(Hr{$I6pwse7v8b1w7VugGaSC`XUrAmI zxGn37xf4bH^~GFk5jyR9|I@j45U&-DJ6~tsUu*?Uw85lowQV%I0)dK^=Np2t#-PdJ zXvK#Rt@x`PtvDq|D^AhOWQZ<7F+O4ADLOz%@d{|-c*QAN_EYZxxe>#%;kCE710VZO zGx`fKYL^+EmKmLv89@PzPKOvl6EiwJ%1E*!9M6g<2$?cW8{%25OJTD>JWJL*7@N-? zT$wZ<&;|qp>-_;7ED7L^HHvsV_{{%EdYpqzsYC;l52z3@3DCadG~O3oMnCl9fXTto#2fxE2Eqjcpl2yMY?g8d1;qx8l$*}^1iJ4}bV+7o=o!u#wrcSNExsvIx? z*cP0h#{U`PD9s(i#sHI(=o?|B_=$~$1c8XKmD@N;24VeSLX<{7XrvtrZQwW-piK5d zIgAnpktJSr9#BBWz;_H?d}NFazJE?i$6Hsd~TG5<^<0BtR@ez<9L@PjsN2rl# zMOk(`5M*uutqgcL2Z_}{fH5q571SlzyUZF#V_^?XCn+d4ezZM`pfTc=08t#hN^*8h{dt#87-tpQ!g+aidl z&vZ@F!z5)kcv$mOi4O3<9{t~YV5=pEYn$Y7)nkY2>G#4Mt`EmJTxUidu1~??I+-<% z=zD;-^}Y6mpa(YMoyKDC^vx@iUHX%kW}}VNsE<9X7;N#rm&0d}S@VgdYzp3~jq8iy z)v(BQy;E(M-b3)&ZIT~(q4r)A_AyP%L+$-0{OB{S2({H_`SBNOmzcq!%$1&b66lZ_ zeCTD;D^hB=$!&NR%D=zL?G^Amlz(T<@*^?S{uBsGuf-tXf?0kvhWZE1&7rDPMij#h z3ekWe3Z7qlqwC3Yj+_%gSFRx&!Qa{}%2onyWI+klUxJatoJgbzo^E&_!|NV0lIwJH^vb{1CYoz1?S-5hApHsF z-0J8v4Ro{F*8q2W9Yl2+Xs(WCGMN{BO{E#De{EZ{_BSuRyl(v~uO4dYzNJhW|0BEa zynowXl(y}lv~43n>XtIRYiC}RXNvQ)(t^>vqOiL59*PL?N%uu3;zj`xm&ZzZUrGpla$iDO+S^nZo--CrqRrG(=y0hH-S0f%r%P6 zLaA9+G(Vf~22d%u!yA`CvRchA$5l#t?P937gzpa`tTytuplZk9)kgG}LL374PKp2o zbmG*&WN~^RMw}TyP+u<=2ejfNfeB(tAX@xIAWD3k%E?5Q0{m@|z9a>8$U2NGL?2}0 z>hNe)fnFblj#MFgU4SMm$D?JL!(IUhxFYW_23bU)CW`+dIN645<{|9T0jvh6^S?pkq5G8!39_$cXqz&SRO{JmM%AoyT@yYg!Q@sr#>xJ7(ib)m+W0Lp= z+fNVF(HI$Y_Omkwz_|&M_nUhUF)y#FPz3c%D?i-T9Z^g57CR%TSE>EOHA#L*+=0bKHMz*lsoe==*< z(_yjR%{bW1T#!1Sgev9=Y5eLGhj15;olOp}=bR4yr(L4I3A+-_I3Li0^8p7TAK*;{ zl5uE#4pc@{0)NXz)0RR?pd=qs0(^dO&SCj1P=Xc6ar3~}I(_owa_wiItz*NHg7U;scAdpJX^%+5eqY*njEu%@HI-C^xBX)db)*2uR zIiX1O;o^~$kj$?RJgfeEJ8Hluh?Kl(qI+?w01C*mz*nj%r7tnken1WP1qTKT8*H|p zQ0UnFPLuuqp)zYo@8D@XfSC*%%WiDzN6g3ic(M$G_es6oe~3;UNnwnnZYC|Ew&vl~ z&3-9$&MGH?TaT zF@iCUUDDW=ZLDm@bn=9xwvf7l<&Q*yFMf%w8lL_T@^mdK|E01=&iM3%XM93_0c3op z;Ed1T!ZSW28JtN=a4JlT5u%sCp5OdQ;&gKCR)nljw*-+hNuzW#64+d6cS_l_P~xY7 sYR|=4Aaq~oz(o?v62j}$cT@O|MNc`8RcDdU5euW2Dvt6lK=n! diff --git a/weegui.lst b/weegui.lst new file mode 100644 index 0000000..5740876 --- /dev/null +++ b/weegui.lst @@ -0,0 +1,4904 @@ +ca65 V2.13.3 - (C) Copyright 1998-2012 Ullrich von Bassewitz +Main file : weegui.s +Current file: weegui.s + +000000r 1 ; +000000r 1 ; gui.s +000000r 1 ; Top level management routines +000000r 1 ; +000000r 1 ; Created by Quinn Dunki on 8/15/14. +000000r 1 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +000000r 1 ; +000000r 1 +000000r 1 +000000r 1 .org $7e00 +007E00 1 +007E00 1 ; Common definitions +007E00 1 +007E00 1 .include "zeropage.s" +007E00 2 ; +007E00 2 ; zeropage.s +007E00 2 ; Zero page information +007E00 2 ; +007E00 2 ; Created by Quinn Dunki on 8/15/14. +007E00 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +007E00 2 ; +007E00 2 +007E00 2 +007E00 2 ; Reserved locations +007E00 2 +007E00 2 INVERSE = $32 ; Text output state +007E00 2 CH = $24 ; Cursor X pos +007E00 2 CV = $25 ; Cursor Y pos +007E00 2 BASL = $28 ; Current video memory line +007E00 2 BASH = $29 ; Current video memory line +007E00 2 +007E00 2 ; Zero page locations we use (unused by Monitor, Applesoft, or ProDOS) +007E00 2 PARAM0 = $06 +007E00 2 PARAM1 = $07 +007E00 2 PARAM2 = $08 +007E00 2 PARAM3 = $09 +007E00 2 SCRATCH0 = $19 +007E00 2 SCRATCH1 = $1a +007E00 2 +007E00 1 .include "switches.s" +007E00 2 ; +007E00 2 ; switches.s +007E00 2 ; Softswitches for Apple ][ +007E00 2 ; +007E00 2 ; Created by Quinn Dunki on 8/15/14. +007E00 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +007E00 2 ; +007E00 2 +007E00 2 +007E00 2 PAGE2 = $c01c ; Read bit 7 +007E00 2 PAGE2OFF = $c054 ; Read/Write +007E00 2 PAGE2ON = $c055 ; Read/Write +007E00 2 +007E00 2 COL80 = $c01f ; Read bit 7 +007E00 2 COL80OFF = $c00c ; Write +007E00 2 COL80ON = $c00d ; Write +007E00 2 +007E00 2 STORE80 = $c018 ; Read bit 7 +007E00 2 STORE80OFF = $c000 ; Write +007E00 2 STORE80ON = $c001 ; Write +007E00 2 +007E00 2 TEXT = $c01a ; Read bit 7 +007E00 2 TEXTOFF = $c050 ; Read/Write +007E00 2 TEXTON = $C051 ; Read/Write +007E00 2 +007E00 2 KBD = $c000 ; Read +007E00 2 KBDSTRB = $c010 ; Read/Write +007E00 2 +007E00 2 RDVBLBAR = $C019 ; Read bit 7 (active low) +007E00 2 +007E00 2 OURCH = $057b ; 80 col cursor position (H) +007E00 2 OURCV = $05fb ; 80 col cursor position (V) +007E00 2 +007E00 1 .include "macros.s" +007E00 2 ; +007E00 2 ; macros.s +007E00 2 ; Generally useful macros for 6502 code +007E00 2 ; +007E00 2 ; Created by Quinn Dunki on 8/15/14. +007E00 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +007E00 2 ; +007E00 2 +007E00 2 +007E00 2 ; Macros +007E00 2 +007E00 2 .macro SETSWITCH name ; Sets the named softswitch (assumes write method) +007E00 2 sta name +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro SAVE_AXY ; Saves all registers +007E00 2 pha +007E00 2 phx +007E00 2 phy +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro RESTORE_AXY ; Restores all registers +007E00 2 ply +007E00 2 plx +007E00 2 pla +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro SAVE_AY ; Saves accumulator and Y index +007E00 2 pha +007E00 2 phy +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro RESTORE_AY ; Restores accumulator and Y index +007E00 2 ply +007E00 2 pla +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro SAVE_AX ; Saves accumulator and X index +007E00 2 pha +007E00 2 phx +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro RESTORE_AX ; Restores accumulator and X index +007E00 2 plx +007E00 2 pla +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro SAVE_XY ; Saves X and Y index +007E00 2 phx +007E00 2 phy +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro RESTORE_XY ; Restores X and Y index +007E00 2 ply +007E00 2 plx +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro SAVE_ZPP ; Saves Zero Page locations we use for parameters +007E00 2 lda PARAM0 +007E00 2 pha +007E00 2 lda PARAM1 +007E00 2 pha +007E00 2 lda PARAM2 +007E00 2 pha +007E00 2 lda PARAM3 +007E00 2 pha +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro RESTORE_ZPP ; Restores Zero Page locations we use for parameters +007E00 2 pla +007E00 2 sta PARAM3 +007E00 2 pla +007E00 2 sta PARAM2 +007E00 2 pla +007E00 2 sta PARAM1 +007E00 2 pla +007E00 2 sta PARAM0 +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro SAVE_ZPS ; Saves Zero Page locations we use for scratch +007E00 2 lda SCRATCH0 +007E00 2 pha +007E00 2 lda SCRATCH1 +007E00 2 pha +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro RESTORE_ZPS ; Restores Zero Page locations we use for scratch +007E00 2 pla +007E00 2 sta SCRATCH1 +007E00 2 pla +007E00 2 sta SCRATCH0 +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro PARAM16 addr +007E00 2 lda #addr +007E00 2 sta PARAM1 +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro CALL16 func,addr +007E00 2 PARAM16 addr +007E00 2 jsr func +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007E00 2 ; Rendering macros +007E00 2 ; +007E00 2 +007E00 2 +007E00 2 .macro LDY_AVIEW +007E00 2 asl ; Find our new view record +007E00 2 asl +007E00 2 asl +007E00 2 asl ; Records are 16 bytes wide +007E00 2 tay +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro LDY_ACTIVEVIEW +007E00 2 lda WG_ACTIVEVIEW ; Find our new view record +007E00 2 LDY_AVIEW +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro LDX_ACTIVEVIEW +007E00 2 lda WG_ACTIVEVIEW ; Find our new view record +007E00 2 asl +007E00 2 asl +007E00 2 asl +007E00 2 asl ; Records are 16 bytes wide +007E00 2 tax +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro LDY_FOCUSVIEW +007E00 2 lda WG_FOCUSVIEW ; Find our new view record +007E00 2 LDY_AVIEW +007E00 2 .endmacro +007E00 2 +007E00 2 +007E00 2 .macro VBL_SYNC ; Synchronize with vertical blanking +007E00 2 lda #$80 +007E00 2 ;macroWaitVBLToFinish: +007E00 2 ; bit RDVBLBAR +007E00 2 ; bmi macroWaitVBLToFinish +007E00 2 @macroWaitVBLToStart: +007E00 2 ; bit RDVBLBAR +007E00 2 ; bpl @macroWaitVBLToStart +007E00 2 .endmacro +007E00 2 +007E00 1 +007E00 1 +007E00 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007E00 1 ; Main entry point. BRUN will land here. +007E00 1 main: +007E00 1 20 49 7E jsr WGInit +007E03 1 60 rts ; Don't add any bytes here! +007E04 1 +007E04 1 +007E04 1 ; This is the non-negotiable entry point used by applications Don't move it! +007E04 1 ; $7e04 +007E04 1 +007E04 1 +007E04 1 +007E04 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007E04 1 ; WGDispatch +007E04 1 ; The dispatcher for calling the assembly-language API from assembly programs +007E04 1 ; X: API call number +007E04 1 ; P0-3,Y: Parameters to call, as needed +007E04 1 WGDispatch: +007E04 1 7C 07 7E jmp (WGEntryPointTable,x) +007E07 1 +007E07 1 ; Entry point jump table +007E07 1 WGEntryPointTable: +007E07 1 FF 7E .addr WGClearScreen +007E09 1 29 7F .addr WGDesktop +007E0B 1 4F 89 .addr WGSetCursor +007E0D 1 5C 89 .addr WGSetGlobalCursor +007E0F 1 69 89 .addr WGSyncGlobalCursor +007E11 1 55 7F .addr WGPlot +007E13 1 90 7F .addr WGPrint +007E15 1 98 80 .addr WGFillRect +007E17 1 24 81 .addr WGStrokeRect +007E19 1 15 83 .addr WGFancyRect +007E1B 1 B6 85 .addr WGPaintView +007E1D 1 3A 8A .addr WGViewPaintAll +007E1F 1 16 87 .addr WGEraseViewContents +007E21 1 B9 84 .addr WGCreateView +007E23 1 0F 85 .addr WGCreateCheckbox +007E25 1 5E 85 .addr WGCreateButton +007E27 1 21 89 .addr WGViewSetTitle +007E29 1 38 89 .addr WGViewSetAction +007E2B 1 57 87 .addr WGSelectView +007E2D 1 5D 8A .addr WGViewFromPoint +007E2F 1 64 87 .addr WGViewFocus +007E31 1 77 87 .addr WGViewUnfocus +007E33 1 82 87 .addr WGViewFocusNext +007E35 1 B3 87 .addr WGViewFocusPrev +007E37 1 2D 88 .addr WGViewFocusAction +007E39 1 97 88 .addr WGPendingViewAction +007E3B 1 1D 89 .addr WGPendingView +007E3D 1 92 89 .addr WGScrollX +007E3F 1 A5 89 .addr WGScrollXBy +007E41 1 E6 89 .addr WGScrollY +007E43 1 F9 89 .addr WGScrollYBy +007E45 1 62 8B .addr WGEnableMouse +007E47 1 BE 8B .addr WGDisableMouse +007E49 1 +007E49 1 +007E49 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007E49 1 ; WGInit +007E49 1 ; Initialization. Should be called once at app startup +007E49 1 WGInit: +007E49 1 48 DA 5A SAVE_AXY +007E4C 1 +007E4C 1 ; Reserve our memory in the ProDOS allocator bitmap +007E4C 1 ; +007E4C 1 ; See section 5.1.4 in the ProDOS 8 Technical Reference Manual +007E4C 1 ; for an explanation of these values. We're reserving memory +007E4C 1 ; pages $7e-$95 so that ProDOS won't use our memory for file +007E4C 1 ; buffers, or allow Applesoft to step on us +007E4C 1 ; +007E4C 1 ; Byte in System Bitmap : Bit within byte +007E4C 1 ; 0f:001 +007E4C 1 ; 0f:000 +007E4C 1 ; 10:111 .. 10:000 +007E4C 1 ; 11:111 .. 11:000 +007E4C 1 ; 12:111 +007E4C 1 ; 12:110 +007E4C 1 ; 12:101 +007E4C 1 ; 12:100 +007E4C 1 ; 12:011 +007E4C 1 ; 12:010 +007E4C 1 A9 03 lda #%00000011 +007E4E 1 0C 67 BF tsb MEMBITMAP + $0f +007E51 1 A9 FF lda #$ff +007E53 1 0C 68 BF tsb MEMBITMAP + $10 +007E56 1 0C 69 BF tsb MEMBITMAP + $11 +007E59 1 A9 FC lda #%11111100 +007E5B 1 0C 6A BF tsb MEMBITMAP + $12 +007E5E 1 +007E5E 1 20 80 7E jsr WG80 ; Enter 80-col text mode +007E61 1 20 C6 8D jsr WGInitApplesoft ; Set up Applesoft API +007E64 1 +007E64 1 A0 0F ldy #15 ; Clear our block allocators +007E66 1 WGInit_clearMemLoop: +007E66 1 98 tya +007E67 1 0A asl +007E68 1 0A asl +007E69 1 0A asl +007E6A 1 0A asl +007E6B 1 AA tax +007E6C 1 A9 00 lda #0 +007E6E 1 9D D6 93 sta WG_STRINGS,x +007E71 1 88 dey +007E72 1 10 F2 bpl WGInit_clearMemLoop +007E74 1 +007E74 1 A9 FF lda #$ff +007E76 1 8D CF 92 sta WG_PENDINGACTIONVIEW +007E79 1 8D CE 92 sta WG_FOCUSVIEW +007E7C 1 +007E7C 1 7A FA 68 RESTORE_AXY +007E7F 1 60 rts +007E80 1 +007E80 1 +007E80 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007E80 1 ; WG80 +007E80 1 ; Enables 80 column mode (and enhanced video firmware) +007E80 1 WG80: +007E80 1 48 pha +007E81 1 +007E81 1 A9 A0 lda #$a0 +007E83 1 20 00 C3 jsr $c300 +007E86 1 +007E86 1 8D 51 C0 SETSWITCH TEXTON +007E89 1 8D 54 C0 SETSWITCH PAGE2OFF +007E8C 1 8D 0D C0 SETSWITCH COL80ON +007E8F 1 8D 01 C0 SETSWITCH STORE80ON +007E92 1 +007E92 1 68 pla +007E93 1 60 rts +007E94 1 +007E94 1 +007E94 1 ; Code modules +007E94 1 .include "utility.s" +007E94 2 ; +007E94 2 ; utility.s +007E94 2 ; General utilities for 6502 +007E94 2 ; +007E94 2 ; Created by Quinn Dunki on 8/15/14. +007E94 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +007E94 2 ; +007E94 2 +007E94 2 +007E94 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007E94 2 ; delayShort +007E94 2 ; Sleeps for ~1/30th second +007E94 2 ; +007E94 2 delayShort: +007E94 2 48 DA 5A SAVE_AXY +007E97 2 +007E97 2 A0 06 ldy #$06 ; Loop a bit +007E99 2 delayShortOuter: +007E99 2 A2 FF ldx #$ff +007E9B 2 delayShortInner: +007E9B 2 EA nop +007E9C 2 EA nop +007E9D 2 EA nop +007E9E 2 EA nop +007E9F 2 EA nop +007EA0 2 EA nop +007EA1 2 EA nop +007EA2 2 CA dex +007EA3 2 D0 F6 bne delayShortInner +007EA5 2 88 dey +007EA6 2 D0 F1 bne delayShortOuter +007EA8 2 +007EA8 2 7A FA 68 RESTORE_AXY +007EAB 2 60 rts +007EAC 2 +007EAC 2 .if 0 +007EAC 2 ;;;;;;;;;;;;;;;;;;;;;;; +007EAC 2 ; scanHexDigit +007EAC 2 ; Scans a 4 bit hex value from an ASCII character +007EAC 2 ; A: ASCII character +007EAC 2 ; Out A: Hex value +007EAC 2 ; +007EAC 2 scanHexDigit: +007EAC 2 cmp #'a' +007EAC 2 bcs scanHexDigitLowCase +007EAC 2 cmp #'A' +007EAC 2 bcs scanHexDigitLetter +007EAC 2 sec +007EAC 2 sbc #'0' +007EAC 2 jmp scanHexDigitDone +007EAC 2 +007EAC 2 scanHexDigitLowCase: +007EAC 2 sec +007EAC 2 sbc #32 +007EAC 2 +007EAC 2 scanHexDigitLetter: +007EAC 2 sec +007EAC 2 sbc #55 +007EAC 2 +007EAC 2 scanHexDigitDone: +007EAC 2 rts +007EAC 2 +007EAC 2 +007EAC 2 ;;;;;;;;;;;;;;;;;;;;;;; +007EAC 2 ; scanHex8 +007EAC 2 ; Scans an 8 bit hex value from a string +007EAC 2 ; PARAM0: Pointer to string (LSB) +007EAC 2 ; PARAM1: Pointer to string (MSB) +007EAC 2 ; Y: Offset into string +007EAC 2 ; Out A: 8-bit hex value +007EAC 2 ; Y: One past what we scanned +007EAC 2 ; Side effects: Clobbers S0 +007EAC 2 ; +007EAC 2 scanHex8: +007EAC 2 lda (PARAM0),y +007EAC 2 jsr scanHexDigit +007EAC 2 asl +007EAC 2 asl +007EAC 2 asl +007EAC 2 asl +007EAC 2 sta SCRATCH0 ; Stash first digit for later +007EAC 2 +007EAC 2 iny +007EAC 2 lda (PARAM0),y +007EAC 2 jsr scanHexDigit +007EAC 2 ora SCRATCH0 +007EAC 2 iny ; Be nice and advance Y to end +007EAC 2 rts +007EAC 2 .endif +007EAC 2 +007EAC 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007EAC 2 ; WGStrLen +007EAC 2 ; Finds the length of a null-terminated string +007EAC 2 ; PARAM0: String pointer, LSB +007EAC 2 ; PARAM1: String pointer, MSB +007EAC 2 ; Return: A: String length, not including null +007EAC 2 ; +007EAC 2 WGStrLen: +007EAC 2 5A phy +007EAD 2 +007EAD 2 A0 00 ldy #0 +007EAF 2 WGStrLen_loop: +007EAF 2 B1 06 lda (PARAM0),y +007EB1 2 F0 03 beq WGStrLen_done +007EB3 2 C8 iny +007EB4 2 80 F9 bra WGStrLen_loop +007EB6 2 +007EB6 2 WGStrLen_done: +007EB6 2 98 tya +007EB7 2 7A ply +007EB8 2 60 rts +007EB9 2 +007EB9 2 +007EB9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007EB9 2 ; WGStoreStr +007EB9 2 ; Finds room in our block allocator and copies the given string. +007EB9 2 ; A: Terminator character +007EB9 2 ; PARAM0: String pointer, LSB +007EB9 2 ; PARAM1: String pointer, MSB +007EB9 2 ; Return: PARAM0: Stored string, LSB +007EB9 2 ; PARAM1: Stored string, MSB +007EB9 2 ; Side Effects: Clobbers SA +007EB9 2 ; +007EB9 2 WGStoreStr: +007EB9 2 8D D6 94 sta WG_SCRATCHA +007EBC 2 48 DA 5A SAVE_AXY +007EBF 2 +007EBF 2 A2 00 ldx #0 +007EC1 2 A0 00 ldy #0 +007EC3 2 +007EC3 2 WGStoreStr_findEmptyLoop: +007EC3 2 BD D6 93 lda WG_STRINGS,x +007EC6 2 F0 11 beq WGStoreStr_copy +007EC8 2 8A txa +007EC9 2 18 clc +007ECA 2 69 10 adc #16 ; String blocks are 16 bytes wide +007ECC 2 B0 03 bcs WGStoreStr_noRoom +007ECE 2 AA tax +007ECF 2 80 F2 bra WGStoreStr_findEmptyLoop +007ED1 2 +007ED1 2 WGStoreStr_noRoom: +007ED1 2 A9 00 lda #0 +007ED3 2 85 06 sta PARAM0 +007ED5 2 85 07 sta PARAM1 +007ED7 2 80 22 bra WGStoreStr_done +007ED9 2 +007ED9 2 WGStoreStr_copy: +007ED9 2 DA phx ; Remember the start of our string +007EDA 2 +007EDA 2 WGStoreStr_copyLoop: +007EDA 2 B1 06 lda (PARAM0),y +007EDC 2 CD D6 94 cmp WG_SCRATCHA +007EDF 2 F0 09 beq WGStoreStr_terminate +007EE1 2 9D D6 93 sta WG_STRINGS,x +007EE4 2 E8 inx +007EE5 2 C8 iny +007EE6 2 C0 0F cpy #15 ; Clip string to maximum block size +007EE8 2 D0 F0 bne WGStoreStr_copyLoop +007EEA 2 +007EEA 2 WGStoreStr_terminate: +007EEA 2 A9 00 lda #0 ; Terminate the stored string +007EEC 2 9D D6 93 sta WG_STRINGS,x +007EEF 2 +007EEF 2 68 pla ; Return pointer to the start of the block +007EF0 2 18 clc +007EF1 2 69 D6 adc #WG_STRINGS +007EF9 2 85 07 sta PARAM1 +007EFB 2 +007EFB 2 WGStoreStr_done: +007EFB 2 7A FA 68 RESTORE_AXY +007EFE 2 60 rts +007EFF 2 +007EFF 1 .include "painting.s" +007EFF 2 ; +007EFF 2 ; painting.s +007EFF 2 ; General rendering routines for 80 column text elements +007EFF 2 ; +007EFF 2 ; Created by Quinn Dunki on 8/15/14. +007EFF 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +007EFF 2 ; +007EFF 2 +007EFF 2 +007EFF 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007EFF 2 ; WGClearScreen +007EFF 2 ; Clears the text screen (assumes 80 cols) +007EFF 2 ; Side effects: Clobbers BASL,BASH +007EFF 2 ; +007EFF 2 WGClearScreen: +007EFF 2 +007EFF 2 48 DA 5A SAVE_AXY +007F02 2 8D 54 C0 SETSWITCH PAGE2OFF +007F05 2 A2 17 ldx #23 +007F07 2 +007F07 2 WGClearScreen_lineLoop: +007F07 2 +007F07 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of line +007F0A 2 85 28 sta BASL +007F0C 2 BD D7 94 lda TEXTLINES_H,x +007F0F 2 85 29 sta BASH +007F11 2 +007F11 2 A0 27 ldy #39 +007F13 2 A9 A0 lda #' ' + $80 +007F15 2 +007F15 2 WGClearScreen_charLoop: +007F15 2 91 28 sta (BASL),y +007F17 2 8D 55 C0 SETSWITCH PAGE2ON +007F1A 2 91 28 sta (BASL),y +007F1C 2 8D 54 C0 SETSWITCH PAGE2OFF +007F1F 2 88 dey +007F20 2 10 F3 bpl WGClearScreen_charLoop +007F22 2 +007F22 2 CA dex +007F23 2 10 E2 bpl WGClearScreen_lineLoop +007F25 2 +007F25 2 7A FA 68 RESTORE_AXY +007F28 2 60 rts +007F29 2 +007F29 2 +007F29 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007F29 2 ; WGDesktop +007F29 2 ; Paints the desktop pattern (assumes 80 cols) +007F29 2 ; Side effects: Clobbers BASL,BASH +007F29 2 ; +007F29 2 WGDesktop: +007F29 2 +007F29 2 48 DA 5A SAVE_AXY +007F2C 2 8D 54 C0 SETSWITCH PAGE2OFF +007F2F 2 A2 17 ldx #23 +007F31 2 +007F31 2 WGDesktop_lineLoop: +007F31 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of line +007F34 2 85 28 sta BASL +007F36 2 BD D7 94 lda TEXTLINES_H,x +007F39 2 85 29 sta BASH +007F3B 2 +007F3B 2 A0 27 ldy #39 +007F3D 2 +007F3D 2 WGDesktop_charLoop: +007F3D 2 A9 57 lda #'W' +007F3F 2 91 28 sta (BASL),y +007F41 2 8D 55 C0 SETSWITCH PAGE2ON +007F44 2 A9 56 lda #'V' +007F46 2 91 28 sta (BASL),y +007F48 2 8D 54 C0 SETSWITCH PAGE2OFF +007F4B 2 88 dey +007F4C 2 10 EF bpl WGDesktop_charLoop +007F4E 2 +007F4E 2 CA dex +007F4F 2 10 E0 bpl WGDesktop_lineLoop +007F51 2 +007F51 2 7A FA 68 RESTORE_AXY +007F54 2 60 rts +007F55 2 +007F55 2 +007F55 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007F55 2 ; WGPlot +007F55 2 ; Plots a character at global cursor position (assumes 80 cols) +007F55 2 ; A: Character to plot (Apple format) +007F55 2 ; Side effects: Clobbers BASL,BASH +007F55 2 ; +007F55 2 WGPlot: +007F55 2 DA 5A SAVE_XY +007F57 2 48 pha +007F58 2 +007F58 2 AE CA 92 ldx WG_CURSORY +007F5B 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of point +007F5E 2 85 28 sta BASL +007F60 2 BD D7 94 lda TEXTLINES_H,x +007F63 2 85 29 sta BASH +007F65 2 +007F65 2 AD C9 92 lda WG_CURSORX +007F68 2 4A lsr +007F69 2 18 clc +007F6A 2 65 28 adc BASL +007F6C 2 85 28 sta BASL +007F6E 2 A9 00 lda #$0 +007F70 2 65 29 adc BASH +007F72 2 85 29 sta BASH +007F74 2 +007F74 2 AD C9 92 lda WG_CURSORX ; X even? +007F77 2 29 01 and #$01 +007F79 2 D0 09 bne WGPlot_xOdd +007F7B 2 +007F7B 2 8D 55 C0 SETSWITCH PAGE2ON ; Plot the character +007F7E 2 68 pla +007F7F 2 92 28 sta (BASL) +007F81 2 4C 8A 7F jmp WGPlot_done +007F84 2 +007F84 2 WGPlot_xOdd: +007F84 2 8D 54 C0 SETSWITCH PAGE2OFF ; Plot the character +007F87 2 68 pla +007F88 2 92 28 sta (BASL) +007F8A 2 +007F8A 2 WGPlot_done: +007F8A 2 8D 54 C0 SETSWITCH PAGE2OFF +007F8D 2 7A FA RESTORE_XY +007F8F 2 60 rts +007F90 2 +007F90 2 +007F90 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +007F90 2 ; WGPrint +007F90 2 ; Prints a null-terminated ASCII string at the current view's +007F90 2 ; cursor position. Clips to current view. +007F90 2 ; PARAM0: String pointer, LSB +007F90 2 ; PARAM1: String pointer, MSB +007F90 2 ; Side effects: Clobbers SA,BASL,BASH +007F90 2 ; +007F90 2 WGPrint: +007F90 2 48 DA 5A SAVE_AXY +007F93 2 A5 19 48 A5 SAVE_ZPS +007F97 2 1A 48 +007F99 2 +007F99 2 AD CC 92 lda WG_LOCALCURSORY +007F9C 2 CD D4 92 cmp WG_VIEWCLIP+3 +007F9F 2 B0 35 bcs WGPrint_leapDone ; Entire string is below the clip box +007FA1 2 +007FA1 2 20 AC 7E jsr WGStrLen ; We'll need the length of the string +007FA4 2 85 1A sta SCRATCH1 +007FA6 2 +007FA6 2 AD CD 92 0A LDX_ACTIVEVIEW ; Cache view width for later +007FAA 2 0A 0A 0A AA +007FAE 2 BD DD 92 lda WG_VIEWRECORDS+7,x +007FB1 2 8D D6 94 sta WG_SCRATCHA +007FB4 2 +007FB4 2 A0 00 ldy #0 +007FB6 2 +007FB6 2 WGPrint_lineLoopFirst: ; Calculating start of first line is slightly different +007FB6 2 AD CC 92 lda WG_LOCALCURSORY +007FB9 2 CD D2 92 cmp WG_VIEWCLIP+1 +007FBC 2 90 1A bcc WGPrint_skipToEndFirst ; This line is above the clip box +007FBE 2 +007FBE 2 AD CB 92 lda WG_LOCALCURSORX ; Find start of line within clip box +007FC1 2 CD D1 92 cmp WG_VIEWCLIP+0 +007FC4 2 B0 54 bcs WGPrint_visibleChars +007FC6 2 +007FC6 2 AD D1 92 lda WG_VIEWCLIP+0 ; Line begins before left clip plane +007FC9 2 38 sec ; Advance string index and advance cursor into clip box +007FCA 2 ED CB 92 sbc WG_LOCALCURSORX +007FCD 2 A8 tay +007FCE 2 AD D1 92 lda WG_VIEWCLIP+0 +007FD1 2 8D CB 92 sta WG_LOCALCURSORX +007FD4 2 80 44 bra WGPrint_visibleChars +007FD6 2 +007FD6 2 WGPrint_leapDone: +007FD6 2 80 6A bra WGPrint_done +007FD8 2 +007FD8 2 WGPrint_skipToEndFirst: +007FD8 2 AD D6 94 lda WG_SCRATCHA ; Skip string index ahead by distance to EOL +007FDB 2 38 sec +007FDC 2 ED CB 92 sbc WG_LOCALCURSORX +007FDF 2 C5 1A cmp SCRATCH1 +007FE1 2 B0 5F bcs WGPrint_done ; EOL is past the end of the string, so we're done +007FE3 2 A8 tay +007FE4 2 +007FE4 2 AD D6 94 lda WG_SCRATCHA ; Skip cursor ahead to EOL +007FE7 2 8D CB 92 sta WG_LOCALCURSORX +007FEA 2 80 6A bra WGPrint_nextLine +007FEC 2 +007FEC 2 WGPrint_skipToEnd: +007FEC 2 98 tya ; Skip string index ahead by distance to EOL +007FED 2 18 clc +007FEE 2 6D D6 94 adc WG_SCRATCHA +007FF1 2 C5 1A cmp SCRATCH1 +007FF3 2 B0 4D bcs WGPrint_done ; EOL is past the end of the string, so we're done +007FF5 2 A8 tay +007FF6 2 +007FF6 2 AD D6 94 lda WG_SCRATCHA ; Skip cursor ahead to EOL +007FF9 2 8D CB 92 sta WG_LOCALCURSORX +007FFC 2 80 58 bra WGPrint_nextLine +007FFE 2 +007FFE 2 WGPrint_lineLoop: +007FFE 2 AD CC 92 lda WG_LOCALCURSORY +008001 2 CD D2 92 cmp WG_VIEWCLIP+1 +008004 2 90 E6 bcc WGPrint_skipToEnd ; This line is above the clip box +008006 2 +008006 2 AD CB 92 lda WG_LOCALCURSORX ; Find start of line within clip box +008009 2 CD D1 92 cmp WG_VIEWCLIP+0 +00800C 2 B0 0C bcs WGPrint_visibleChars +00800E 2 +00800E 2 98 tya +00800F 2 18 clc +008010 2 6D D1 92 adc WG_VIEWCLIP+0 ; Jump ahead by left span +008013 2 A8 tay +008014 2 +008014 2 AD D1 92 lda WG_VIEWCLIP+0 ; Set cursor to left edge of visible area +008017 2 8D CB 92 sta WG_LOCALCURSORX +00801A 2 +00801A 2 WGPrint_visibleChars: +00801A 2 20 69 89 jsr WGSyncGlobalCursor +00801D 2 +00801D 2 A5 32 lda INVERSE +00801F 2 C9 3F cmp #CHAR_INVERSE +008021 2 F0 4E beq WGPrint_charLoopInverse +008023 2 +008023 2 WGPrint_charLoopNormal: +008023 2 B1 06 lda (PARAM0),y ; Draw current character +008025 2 F0 1B beq WGPrint_done +008027 2 09 80 ora #%10000000 +008029 2 20 55 7F jsr WGPlot +00802C 2 C8 iny +00802D 2 +00802D 2 EE C9 92 inc WG_CURSORX ; Advance cursors +008030 2 EE CB 92 inc WG_LOCALCURSORX +008033 2 +008033 2 AD CB 92 lda WG_LOCALCURSORX +008036 2 CD D6 94 cmp WG_SCRATCHA ; Check for wrap boundary +008039 2 F0 1B beq WGPrint_nextLine +00803B 2 CD D3 92 cmp WG_VIEWCLIP+2 ; Check for right clip plane +00803E 2 F0 0C beq WGPrint_endVisible +008040 2 80 E1 bra WGPrint_charLoopNormal +008042 2 +008042 2 WGPrint_done: ; This is in the middle here to keep local branches in range +008042 2 68 85 1A 68 RESTORE_ZPS +008046 2 85 19 +008048 2 7A FA 68 RESTORE_AXY +00804B 2 60 rts +00804C 2 +00804C 2 WGPrint_endVisible: +00804C 2 98 tya +00804D 2 18 clc +00804E 2 6D D5 92 adc WG_VIEWCLIP+4 ; Advance string index by right span +008051 2 C5 1A cmp SCRATCH1 +008053 2 B0 ED bcs WGPrint_done +008055 2 A8 tay +008056 2 +008056 2 WGPrint_nextLine: +008056 2 EE CC 92 inc WG_LOCALCURSORY ; Advance cursor +008059 2 AD CC 92 lda WG_LOCALCURSORY +00805C 2 CD D4 92 cmp WG_VIEWCLIP+3 ; Check for bottom clip plane +00805F 2 F0 E1 beq WGPrint_done +008061 2 DD DE 92 cmp WG_VIEWRECORDS+8,x ; Check for bottom of view +008064 2 F0 DC beq WGPrint_done +008066 2 B1 06 lda (PARAM0),y ; Check for end string landing exactly at line end +008068 2 F0 D8 beq WGPrint_done +00806A 2 +00806A 2 A9 00 lda #0 ; Wrap to next line +00806C 2 8D CB 92 sta WG_LOCALCURSORX +00806F 2 80 8D bra WGPrint_lineLoop +008071 2 +008071 2 WGPrint_charLoopInverse: +008071 2 B1 06 lda (PARAM0),y ; Draw current character +008073 2 F0 CD beq WGPrint_done +008075 2 C9 60 cmp #$60 +008077 2 90 04 bcc WGPrint_charLoopInverseLow +008079 2 29 7F and #%01111111 ; Inverse lowercase is in alternate character set +00807B 2 80 02 bra WGPrint_charLoopInversePlot +00807D 2 +00807D 2 WGPrint_charLoopInverseLow: +00807D 2 29 3F and #%00111111 ; Normal inverse +00807F 2 +00807F 2 WGPrint_charLoopInversePlot: +00807F 2 20 55 7F jsr WGPlot +008082 2 C8 iny +008083 2 +008083 2 EE C9 92 inc WG_CURSORX ; Advance cursors +008086 2 EE CB 92 inc WG_LOCALCURSORX +008089 2 +008089 2 AD CB 92 lda WG_LOCALCURSORX +00808C 2 CD D6 94 cmp WG_SCRATCHA ; Check for wrap boundary +00808F 2 F0 C5 beq WGPrint_nextLine +008091 2 CD D3 92 cmp WG_VIEWCLIP+2 ; Check for right clip plane +008094 2 F0 B6 beq WGPrint_endVisible +008096 2 80 D9 bra WGPrint_charLoopInverse +008098 2 +008098 2 +008098 1 .include "rects.s" +008098 2 ; +008098 2 ; rects.s +008098 2 ; Rectangle rendering routines for 80 column text elements +008098 2 ; +008098 2 ; Created by Quinn Dunki on 8/15/14. +008098 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +008098 2 ; +008098 2 +008098 2 +008098 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008098 2 ; WGFillRect +008098 2 ; Fills a rectangle (assumes 80 cols) +008098 2 ; PARAM0: Left edge +008098 2 ; PARAM1: Top edge +008098 2 ; PARAM2: Width +008098 2 ; PARAM3: Height +008098 2 ; Y: Character to fill (Apple format) +008098 2 ; Side effects: Clobbers Y,S0,BASL,BASH +008098 2 ; +008098 2 WGFillRect: +008098 2 48 DA SAVE_AX +00809A 2 84 19 sty SCRATCH0 +00809C 2 +00809C 2 18 clc ; Compute bottom edge +00809D 2 A5 07 lda PARAM1 +00809F 2 65 09 adc PARAM3 +0080A1 2 3A dec +0080A2 2 AA tax +0080A3 2 +0080A3 2 WGFillRect_vertLoop: +0080A3 2 DA phx ; We'll need X back for now, but save the line number +0080A4 2 +0080A4 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect +0080A7 2 85 28 sta BASL +0080A9 2 BD D7 94 lda TEXTLINES_H,x +0080AC 2 85 29 sta BASH +0080AE 2 +0080AE 2 A5 06 lda PARAM0 +0080B0 2 4A lsr +0080B1 2 18 clc +0080B2 2 65 28 adc BASL +0080B4 2 85 28 sta BASL +0080B6 2 A9 00 lda #$0 +0080B8 2 65 29 adc BASH +0080BA 2 85 29 sta BASH +0080BC 2 +0080BC 2 A5 06 lda PARAM0 ; Left edge even? +0080BE 2 29 01 and #$01 +0080C0 2 D0 2F bne WGFillRect_horzLoopOdd +0080C2 2 +0080C2 2 ; CASE 1: Left edge even-aligned, even width +0080C2 2 8D 54 C0 SETSWITCH PAGE2OFF +0080C5 2 A5 08 lda PARAM2 +0080C7 2 4A lsr +0080C8 2 A8 tay ; Iterate w/2 +0080C9 2 88 dey +0080CA 2 5A phy ; We'll reuse this calculation for the odd columns +0080CB 2 +0080CB 2 A5 19 lda SCRATCH0 ; Prepare to plot +0080CD 2 WGFillRect_horzLoopEvenAligned0: ; Draw even columns +0080CD 2 91 28 sta (BASL),y ; Plot the character +0080CF 2 88 dey +0080D0 2 10 FB bpl WGFillRect_horzLoopEvenAligned0 ; Loop for w/2 +0080D2 2 +0080D2 2 8D 55 C0 SETSWITCH PAGE2ON ; Prepare for odd columns +0080D5 2 7A ply ; Iterate w/2 again +0080D6 2 +0080D6 2 WGFillRect_horzLoopEvenAligned1: ; Draw odd columns +0080D6 2 91 28 sta (BASL),y ; Plot the character +0080D8 2 88 dey +0080D9 2 10 FB bpl WGFillRect_horzLoopEvenAligned1 ; Loop for w/2 +0080DB 2 +0080DB 2 A5 08 lda PARAM2 ; Is width even? +0080DD 2 29 01 and #$01 +0080DF 2 F0 08 beq WGFillRect_horzLoopEvenAlignedEvenWidth +0080E1 2 +0080E1 2 ; CASE 1a: Left edge even aligned, odd width +0080E1 2 A5 08 lda PARAM2 ; Fill in extra last column +0080E3 2 4A lsr +0080E4 2 A8 tay +0080E5 2 A5 19 lda SCRATCH0 ; Plot the character +0080E7 2 91 28 sta (BASL),y +0080E9 2 +0080E9 2 WGFillRect_horzLoopEvenAlignedEvenWidth: +0080E9 2 FA plx ; Prepare for next row +0080EA 2 CA dex +0080EB 2 E4 07 cpx PARAM1 +0080ED 2 B0 B4 bcs WGFillRect_vertLoop +0080EF 2 80 2D bra WGFillRect_done +0080F1 2 +0080F1 2 WGFillRect_horzLoopOdd: +0080F1 2 ; CASE 2: Left edge odd-aligned, even width +0080F1 2 8D 55 C0 SETSWITCH PAGE2ON +0080F4 2 A5 08 lda PARAM2 +0080F6 2 4A lsr +0080F7 2 A8 tay ; Iterate w/2 +0080F8 2 5A phy ; We'll reuse this calculation for the even columns +0080F9 2 +0080F9 2 A5 19 lda SCRATCH0 ; Prepare to plot +0080FB 2 WGFillRect_horzLoopOddAligned0: ; Draw even columns +0080FB 2 91 28 sta (BASL),y ; Plot the character +0080FD 2 88 dey +0080FE 2 D0 FB bne WGFillRect_horzLoopOddAligned0 ; Loop for w/2 +008100 2 +008100 2 8D 54 C0 SETSWITCH PAGE2OFF ; Prepare for odd columns +008103 2 7A ply ; Iterate w/2 again, shift left 1 +008104 2 88 dey +008105 2 +008105 2 WGFillRect_horzLoopOddAligned1: ; Draw even columns +008105 2 91 28 sta (BASL),y ; Plot the character +008107 2 88 dey +008108 2 10 FB bpl WGFillRect_horzLoopOddAligned1 ; Loop for w/2 +00810A 2 +00810A 2 A5 08 lda PARAM2 ; Is width even? +00810C 2 29 01 and #$01 +00810E 2 F0 08 beq WGFillRect_horzLoopOddAlignedEvenWidth +008110 2 +008110 2 ; CASE 2a: Left edge odd aligned, odd width +008110 2 A5 08 lda PARAM2 ; Fill in extra last column +008112 2 4A lsr +008113 2 A8 tay +008114 2 A5 19 lda SCRATCH0 ; Plot the character +008116 2 91 28 sta (BASL),y +008118 2 +008118 2 WGFillRect_horzLoopOddAlignedEvenWidth: +008118 2 FA plx ; Prepare for next row +008119 2 CA dex +00811A 2 E4 07 cpx PARAM1 +00811C 2 B0 85 bcs WGFillRect_vertLoop +00811E 2 +00811E 2 WGFillRect_done: +00811E 2 8D 54 C0 SETSWITCH PAGE2OFF +008121 2 FA 68 RESTORE_AX +008123 2 60 rts +008124 2 +008124 2 +008124 2 +008124 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008124 2 ; WGStrokeRect +008124 2 ; Strokes a rectangle (assumes 80 cols) +008124 2 ; PARAM0: Left edge +008124 2 ; PARAM1: Top edge +008124 2 ; PARAM2: Width +008124 2 ; PARAM3: Height +008124 2 ; Side effects: Clobbers BASL,BASH +008124 2 ; +008124 2 CH_TOP = '_'+$80 +008124 2 CH_BOTTOM = 'L' +008124 2 CH_LEFT = 'Z' +008124 2 CH_RIGHT = '_' +008124 2 CH_DOUBLE = '\' +008124 2 +008124 2 .macro PLOTHLINE +008124 2 lda (BASL),y +008124 2 cmp SCRATCH0 +008124 2 beq @PLOTHLINE_skip +008124 2 cmp #CH_DOUBLE +008124 2 beq @PLOTHLINE_skip +008124 2 cmp #CH_BOTTOM +008124 2 beq @PLOTHLINE_double +008124 2 cmp #CH_TOP +008124 2 beq @PLOTHLINE_double +008124 2 lda SCRATCH0 +008124 2 bra @PLOTHLINE_plot +008124 2 @PLOTHLINE_double: +008124 2 lda #CH_DOUBLE +008124 2 @PLOTHLINE_plot: +008124 2 sta (BASL),y +008124 2 @PLOTHLINE_skip: +008124 2 .endmacro +008124 2 +008124 2 +008124 2 WGStrokeRect: +008124 2 48 DA 5A SAVE_AXY +008127 2 A5 19 48 A5 SAVE_ZPS +00812B 2 1A 48 +00812D 2 +00812D 2 ; Top and bottom edges +00812D 2 ; +00812D 2 A6 07 ldx PARAM1 ; Start with top edge +00812F 2 CA dex +008130 2 A9 DF lda #CH_TOP +008132 2 85 19 sta SCRATCH0 +008134 2 +008134 2 WGStrokeRect_horzEdge: +008134 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect +008137 2 85 28 sta BASL +008139 2 BD D7 94 lda TEXTLINES_H,x +00813C 2 85 29 sta BASH +00813E 2 +00813E 2 A5 06 lda PARAM0 +008140 2 4A lsr +008141 2 18 clc +008142 2 65 28 adc BASL +008144 2 85 28 sta BASL +008146 2 A9 00 lda #$0 +008148 2 65 29 adc BASH +00814A 2 85 29 sta BASH +00814C 2 +00814C 2 A5 06 lda PARAM0 ; Left edge even? +00814E 2 29 01 and #$01 +008150 2 F0 03 beq WGStrokeRect_horzEdgeEven +008152 2 4C E3 81 jmp WGStrokeRect_horzLoopOdd +008155 2 +008155 2 WGStrokeRect_horzEdgeEven: +008155 2 A5 08 lda PARAM2 +008157 2 C9 01 cmp #1 ; Width==1 is a special case +008159 2 D0 03 bne WGStrokeRect_horzLoopEvenAlignedNormalWidth +00815B 2 4C DE 81 jmp WGStrokeRect_horzLoopEvenAlignedOneWidth +00815E 2 +00815E 2 WGStrokeRect_horzLoopEvenAlignedNormalWidth: +00815E 2 ; CASE 1: Left edge even-aligned, even width +00815E 2 8D 54 C0 SETSWITCH PAGE2OFF +008161 2 A5 08 lda PARAM2 +008163 2 4A lsr +008164 2 A8 tay ; Start at right edge +008165 2 88 dey +008166 2 5A phy ; We'll reuse this calculation for the odd columns +008167 2 +008167 2 WGStrokeRect_horzLoopEvenAligned0: ; Draw even columns +008167 2 B1 28 C5 19 PLOTHLINE ; Plot the character +00816B 2 F0 14 C9 5C +00816F 2 F0 10 C9 4C +008181 2 88 dey +008182 2 10 E3 bpl WGStrokeRect_horzLoopEvenAligned0 ; Loop for w/2 +008184 2 +008184 2 8D 55 C0 SETSWITCH PAGE2ON ; Prepare for odd columns +008187 2 7A ply ; Start at right edge again +008188 2 +008188 2 WGStrokeRect_horzLoopEvenAligned1: ; Draw odd columns +008188 2 B1 28 C5 19 PLOTHLINE ; Plot the character +00818C 2 F0 14 C9 5C +008190 2 F0 10 C9 4C +0081A2 2 88 dey +0081A3 2 10 E3 bpl WGStrokeRect_horzLoopEvenAligned1 ; Loop for w/2 +0081A5 2 +0081A5 2 A5 08 lda PARAM2 ; Is width even? +0081A7 2 29 01 and #$01 +0081A9 2 F0 1E beq WGStrokeRect_horzLoopEvenAlignedEvenWidth +0081AB 2 +0081AB 2 WGStrokeRect_horzLoopEvenAlignedOddWidth: +0081AB 2 ; CASE 1a: Left edge even aligned, odd width +0081AB 2 A5 08 lda PARAM2 ; Fill in extra last column +0081AD 2 4A lsr +0081AE 2 A8 tay +0081AF 2 B1 28 C5 19 PLOTHLINE ; Plot the character +0081B3 2 F0 14 C9 5C +0081B7 2 F0 10 C9 4C +0081C9 2 +0081C9 2 WGStrokeRect_horzLoopEvenAlignedEvenWidth: +0081C9 2 E8 inx +0081CA 2 E4 07 cpx PARAM1 +0081CC 2 F0 03 beq WGStrokeRect_horzLoopEvenAlignedEvenWidthBottom +0081CE 2 4C 6C 82 jmp WGStrokeRect_vertEdge +0081D1 2 +0081D1 2 WGStrokeRect_horzLoopEvenAlignedEvenWidthBottom: +0081D1 2 18 clc ; Prepare for bottom edge +0081D2 2 A5 07 lda PARAM1 +0081D4 2 65 09 adc PARAM3 +0081D6 2 AA tax +0081D7 2 A9 4C lda #CH_BOTTOM +0081D9 2 85 19 sta SCRATCH0 +0081DB 2 4C 34 81 jmp WGStrokeRect_horzEdge +0081DE 2 +0081DE 2 WGStrokeRect_horzLoopEvenAlignedOneWidth: +0081DE 2 8D 55 C0 SETSWITCH PAGE2ON +0081E1 2 80 C8 bra WGStrokeRect_horzLoopEvenAlignedOddWidth +0081E3 2 +0081E3 2 WGStrokeRect_horzLoopOdd: +0081E3 2 ; CASE 2: Left edge odd-aligned, even width +0081E3 2 +0081E3 2 A5 08 lda PARAM2 +0081E5 2 C9 01 cmp #1 ; Width==1 is a special case +0081E7 2 F0 7E beq WGStrokeRect_horzLoopOddAlignedOneWidth +0081E9 2 +0081E9 2 8D 55 C0 SETSWITCH PAGE2ON +0081EC 2 A5 08 lda PARAM2 +0081EE 2 4A lsr +0081EF 2 A8 tay ; Iterate w/2 +0081F0 2 5A phy ; We'll reuse this calculation for the even columns +0081F1 2 +0081F1 2 WGStrokeRect_horzLoopOddAligned0: ; Draw even columns +0081F1 2 B1 28 C5 19 PLOTHLINE ; Plot the character +0081F5 2 F0 14 C9 5C +0081F9 2 F0 10 C9 4C +00820B 2 88 dey +00820C 2 D0 E3 bne WGStrokeRect_horzLoopOddAligned0 ; Loop for w/2 +00820E 2 +00820E 2 8D 54 C0 SETSWITCH PAGE2OFF ; Prepare for odd columns +008211 2 7A ply ; Iterate w/2 again, shift left 1 +008212 2 88 dey +008213 2 +008213 2 WGStrokeRect_horzLoopOddAligned1: ; Draw even columns +008213 2 B1 28 C5 19 PLOTHLINE ; Plot the character +008217 2 F0 14 C9 5C +00821B 2 F0 10 C9 4C +00822D 2 88 dey +00822E 2 10 E3 bpl WGStrokeRect_horzLoopOddAligned1 ; Loop for w/2 +008230 2 +008230 2 A5 08 lda PARAM2 ; Is width even? +008232 2 29 01 and #$01 +008234 2 F0 1F beq WGStrokeRect_horzLoopOddAlignedEvenWidth +008236 2 +008236 2 WGStrokeRect_horzLoopOddAlignedOddWidth: +008236 2 ; CASE 2a: Left edge odd aligned, odd width +008236 2 A5 08 lda PARAM2 ; Fill in extra last column +008238 2 3A dec +008239 2 4A lsr +00823A 2 A8 tay +00823B 2 B1 28 C5 19 PLOTHLINE ; Plot the character +00823F 2 F0 14 C9 5C +008243 2 F0 10 C9 4C +008255 2 +008255 2 WGStrokeRect_horzLoopOddAlignedEvenWidth: +008255 2 E8 inx +008256 2 E4 07 cpx PARAM1 +008258 2 D0 12 bne WGStrokeRect_vertEdge +00825A 2 18 clc ; Prepare for bottom edge +00825B 2 A5 07 lda PARAM1 +00825D 2 65 09 adc PARAM3 +00825F 2 AA tax +008260 2 A9 4C lda #CH_BOTTOM +008262 2 85 19 sta SCRATCH0 +008264 2 4C 34 81 jmp WGStrokeRect_horzEdge +008267 2 +008267 2 WGStrokeRect_horzLoopOddAlignedOneWidth: +008267 2 8D 54 C0 SETSWITCH PAGE2OFF +00826A 2 80 CA bra WGStrokeRect_horzLoopOddAlignedOddWidth +00826C 2 +00826C 2 WGStrokeRect_vertEdge: +00826C 2 ; Left and right edges +00826C 2 ; +00826C 2 18 clc +00826D 2 A5 07 lda PARAM1 ; Compute bottom edge +00826F 2 65 09 adc PARAM3 +008271 2 85 19 sta SCRATCH0 +008273 2 +008273 2 A6 07 ldx PARAM1 ; Start with top edge +008275 2 +008275 2 WGStrokeRect_vertLoop: +008275 2 +008275 2 DA phx ; We'll need X back for now, but save the line number +008276 2 +008276 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect +008279 2 85 28 sta BASL +00827B 2 BD D7 94 lda TEXTLINES_H,x +00827E 2 85 29 sta BASH +008280 2 +008280 2 A5 06 lda PARAM0 +008282 2 3A dec +008283 2 4A lsr +008284 2 18 clc +008285 2 65 28 adc BASL +008287 2 85 28 sta BASL +008289 2 A9 00 lda #$0 +00828B 2 65 29 adc BASH +00828D 2 85 29 sta BASH +00828F 2 +00828F 2 A5 06 lda PARAM0 ; Left edge even? +008291 2 3A dec +008292 2 29 01 and #$01 +008294 2 D0 38 bne WGStrokeRect_vertLoopOdd +008296 2 +008296 2 ; CASE 1: Left edge even-aligned, even width +008296 2 8D 55 C0 SETSWITCH PAGE2ON +008299 2 A0 00 ldy #$0 +00829B 2 A9 5A lda #CH_LEFT ; Plot the left edge +00829D 2 91 28 sta (BASL),y +00829F 2 +00829F 2 A5 08 lda PARAM2 ; Is width even? +0082A1 2 1A inc +0082A2 2 1A inc +0082A3 2 29 01 and #$01 +0082A5 2 D0 11 bne WGStrokeRect_vertLoopEvenAlignedOddWidth +0082A7 2 +0082A7 2 A5 08 lda PARAM2 ; Calculate right edge +0082A9 2 1A inc +0082AA 2 1A inc +0082AB 2 4A lsr +0082AC 2 3A dec +0082AD 2 A8 tay +0082AE 2 8D 54 C0 SETSWITCH PAGE2OFF +0082B1 2 A9 5F lda #CH_RIGHT ; Plot the right edge +0082B3 2 91 28 sta (BASL),y +0082B5 2 4C C5 82 jmp WGStrokeRect_vertLoopEvenAlignedNextRow +0082B8 2 +0082B8 2 WGStrokeRect_vertLoopEvenAlignedOddWidth: +0082B8 2 ; CASE 1a: Left edge even-aligned, odd width +0082B8 2 8D 55 C0 SETSWITCH PAGE2ON +0082BB 2 A5 08 lda PARAM2 ; Calculate right edge +0082BD 2 1A inc +0082BE 2 1A inc +0082BF 2 4A lsr +0082C0 2 A8 tay +0082C1 2 A9 5F lda #CH_RIGHT ; Plot the right edge +0082C3 2 91 28 sta (BASL),y +0082C5 2 +0082C5 2 WGStrokeRect_vertLoopEvenAlignedNextRow: +0082C5 2 FA plx ; Prepare for next row +0082C6 2 E8 inx +0082C7 2 E4 19 cpx SCRATCH0 +0082C9 2 D0 AA bne WGStrokeRect_vertLoop +0082CB 2 4C 08 83 jmp WGStrokeRect_done +0082CE 2 +0082CE 2 +0082CE 2 WGStrokeRect_vertLoopOdd: +0082CE 2 ; CASE 2: Left edge odd-aligned, even width +0082CE 2 8D 54 C0 SETSWITCH PAGE2OFF +0082D1 2 A0 00 ldy #$0 +0082D3 2 A9 5A lda #CH_LEFT ; Plot the left edge +0082D5 2 91 28 sta (BASL),y +0082D7 2 +0082D7 2 A5 08 lda PARAM2 ; Is width even? +0082D9 2 1A inc +0082DA 2 1A inc +0082DB 2 29 01 and #$01 +0082DD 2 D0 10 bne WGStrokeRect_vertLoopOddAlignedOddWidth +0082DF 2 +0082DF 2 A5 08 lda PARAM2 ; Calculate right edge +0082E1 2 1A inc +0082E2 2 1A inc +0082E3 2 4A lsr +0082E4 2 A8 tay +0082E5 2 8D 55 C0 SETSWITCH PAGE2ON +0082E8 2 A9 5F lda #CH_RIGHT ; Plot the right edge +0082EA 2 91 28 sta (BASL),y +0082EC 2 4C FC 82 jmp WGStrokeRect_vertLoopOddAlignedNextRow +0082EF 2 +0082EF 2 WGStrokeRect_vertLoopOddAlignedOddWidth: +0082EF 2 ; CASE 2a: Left edge odd-aligned, odd width +0082EF 2 8D 54 C0 SETSWITCH PAGE2OFF +0082F2 2 A5 08 lda PARAM2 ; Calculate right edge +0082F4 2 1A inc +0082F5 2 1A inc +0082F6 2 4A lsr +0082F7 2 A8 tay +0082F8 2 A9 5F lda #CH_RIGHT ; Plot the right edge +0082FA 2 91 28 sta (BASL),y +0082FC 2 +0082FC 2 WGStrokeRect_vertLoopOddAlignedNextRow: +0082FC 2 FA plx ; Prepare for next row +0082FD 2 E8 inx +0082FE 2 E4 19 cpx SCRATCH0 +008300 2 D0 03 bne WGStrokeRect_vertLoopJmp +008302 2 4C 08 83 jmp WGStrokeRect_done +008305 2 WGStrokeRect_vertLoopJmp: +008305 2 4C 75 82 jmp WGStrokeRect_vertLoop +008308 2 +008308 2 WGStrokeRect_done: +008308 2 8D 54 C0 SETSWITCH PAGE2OFF +00830B 2 68 85 1A 68 RESTORE_ZPS +00830F 2 85 19 +008311 2 7A FA 68 RESTORE_AXY +008314 2 60 rts +008315 2 +008315 2 +008315 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008315 2 ; WGFancyRect +008315 2 ; Draws a fancy rectangle (assumes 80 cols) +008315 2 ; PARAM0: Left edge +008315 2 ; PARAM1: Top edge +008315 2 ; PARAM2: Width +008315 2 ; PARAM3: Height +008315 2 ; Side effects: Clobbers BASL,BASH +008315 2 ; +008315 2 FR_TOP = '\' +008315 2 FR_BOTTOM = '_'+$80 +008315 2 FR_LEFT = 'Z' +008315 2 FR_RIGHT = 'Z' +008315 2 FR_TOPLEFT = 'Z' +008315 2 FR_TOPRIGHT = '^' +008315 2 FR_TOPRIGHTA = 'R' +008315 2 FR_BOTTOMRIGHT = $7f +008315 2 FR_BOTTOMRIGHTA1 = 'Q' +008315 2 FR_BOTTOMRIGHTA2 = 'P' +008315 2 FR_BOTTOMLEFT = 'Z' +008315 2 FR_BOTTOMLEFTA = 'O' +008315 2 +008315 2 WGFancyRect: +008315 2 48 DA 5A SAVE_AXY +008318 2 A5 19 48 A5 SAVE_ZPS +00831C 2 1A 48 +00831E 2 +00831E 2 ; Top and bottom edges +00831E 2 ; +00831E 2 A6 07 ldx PARAM1 ; Start with top edge +008320 2 CA dex +008321 2 A9 5C lda #FR_TOP +008323 2 85 19 sta SCRATCH0 +008325 2 +008325 2 WGFancyRect_horzEdge: +008325 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect +008328 2 85 28 sta BASL +00832A 2 BD D7 94 lda TEXTLINES_H,x +00832D 2 85 29 sta BASH +00832F 2 +00832F 2 A5 06 lda PARAM0 +008331 2 4A lsr +008332 2 18 clc +008333 2 65 28 adc BASL +008335 2 85 28 sta BASL +008337 2 A9 00 lda #$0 +008339 2 65 29 adc BASH +00833B 2 85 29 sta BASH +00833D 2 +00833D 2 A5 06 lda PARAM0 ; Left edge even? +00833F 2 29 01 and #$01 +008341 2 D0 3B bne WGFancyRect_horzLoopOdd +008343 2 +008343 2 ; CASE 1: Left edge even-aligned, even width +008343 2 8D 54 C0 SETSWITCH PAGE2OFF +008346 2 A5 08 lda PARAM2 +008348 2 4A lsr +008349 2 A8 tay ; Start at right edge +00834A 2 88 dey +00834B 2 5A phy ; We'll reuse this calculation for the odd columns +00834C 2 +00834C 2 WGFancyRect_horzLoopEvenAligned0: ; Draw even columns +00834C 2 A5 19 lda SCRATCH0 ; Plot the character +00834E 2 91 28 sta (BASL),y +008350 2 88 dey +008351 2 10 F9 bpl WGFancyRect_horzLoopEvenAligned0 ; Loop for w/2 +008353 2 +008353 2 8D 55 C0 SETSWITCH PAGE2ON ; Prepare for odd columns +008356 2 7A ply ; Start at right edge again +008357 2 +008357 2 WGFancyRect_horzLoopEvenAligned1: ; Draw odd columns +008357 2 A5 19 lda SCRATCH0 ; Plot the character +008359 2 91 28 sta (BASL),y +00835B 2 88 dey +00835C 2 10 F9 bpl WGFancyRect_horzLoopEvenAligned1 ; Loop for w/2 +00835E 2 +00835E 2 A5 08 lda PARAM2 ; Is width even? +008360 2 29 01 and #$01 +008362 2 F0 08 beq WGFancyRect_horzLoopEvenAlignedEvenWidth +008364 2 +008364 2 WGFancyRect_horzLoopEvenAlignedOddWidth: +008364 2 ; CASE 1a: Left edge even aligned, odd width +008364 2 A5 08 lda PARAM2 ; Fill in extra last column +008366 2 4A lsr +008367 2 A8 tay +008368 2 A5 19 lda SCRATCH0 ; Plot the character +00836A 2 91 28 sta (BASL),y +00836C 2 +00836C 2 WGFancyRect_horzLoopEvenAlignedEvenWidth: +00836C 2 E8 inx +00836D 2 E4 07 cpx PARAM1 +00836F 2 D0 49 bne WGFancyRect_vertEdge +008371 2 18 clc ; Prepare for bottom edge +008372 2 A5 07 lda PARAM1 +008374 2 65 09 adc PARAM3 +008376 2 AA tax +008377 2 A9 DF lda #FR_BOTTOM +008379 2 85 19 sta SCRATCH0 +00837B 2 4C 25 83 jmp WGFancyRect_horzEdge +00837E 2 +00837E 2 WGFancyRect_horzLoopOdd: +00837E 2 ; CASE 2: Left edge odd-aligned, even width +00837E 2 +00837E 2 8D 55 C0 SETSWITCH PAGE2ON +008381 2 A5 08 lda PARAM2 +008383 2 4A lsr +008384 2 A8 tay ; Iterate w/2 +008385 2 5A phy ; We'll reuse this calculation for the even columns +008386 2 +008386 2 WGFancyRect_horzLoopOddAligned0: ; Draw even columns +008386 2 A5 19 lda SCRATCH0 ; Plot the character +008388 2 91 28 sta (BASL),y +00838A 2 88 dey +00838B 2 D0 F9 bne WGFancyRect_horzLoopOddAligned0 ; Loop for w/2 +00838D 2 +00838D 2 8D 54 C0 SETSWITCH PAGE2OFF ; Prepare for odd columns +008390 2 7A ply ; Iterate w/2 again, shift left 1 +008391 2 88 dey +008392 2 +008392 2 WGFancyRect_horzLoopOddAligned1: ; Draw even columns +008392 2 A5 19 lda SCRATCH0 ; Plot the character +008394 2 91 28 sta (BASL),y +008396 2 88 dey +008397 2 10 F9 bpl WGFancyRect_horzLoopOddAligned1 ; Loop for w/2 +008399 2 +008399 2 A5 08 lda PARAM2 ; Is width even? +00839B 2 29 01 and #$01 +00839D 2 F0 09 beq WGFancyRect_horzLoopOddAlignedEvenWidth +00839F 2 +00839F 2 WGFancyRect_horzLoopOddAlignedOddWidth: +00839F 2 ; CASE 2a: Left edge odd aligned, odd width +00839F 2 A5 08 lda PARAM2 ; Fill in extra last column +0083A1 2 3A dec +0083A2 2 4A lsr +0083A3 2 A8 tay +0083A4 2 A5 19 lda SCRATCH0 ; Plot the character +0083A6 2 91 28 sta (BASL),y +0083A8 2 +0083A8 2 WGFancyRect_horzLoopOddAlignedEvenWidth: +0083A8 2 E8 inx +0083A9 2 E4 07 cpx PARAM1 +0083AB 2 D0 0D bne WGFancyRect_vertEdge +0083AD 2 18 clc ; Prepare for bottom edge +0083AE 2 A5 07 lda PARAM1 +0083B0 2 65 09 adc PARAM3 +0083B2 2 AA tax +0083B3 2 A9 DF lda #FR_BOTTOM +0083B5 2 85 19 sta SCRATCH0 +0083B7 2 4C 25 83 jmp WGFancyRect_horzEdge +0083BA 2 +0083BA 2 WGFancyRect_vertEdge: +0083BA 2 ; Left and right edges +0083BA 2 ; +0083BA 2 18 clc +0083BB 2 A5 07 lda PARAM1 ; Compute bottom edge +0083BD 2 65 09 adc PARAM3 +0083BF 2 85 19 sta SCRATCH0 +0083C1 2 +0083C1 2 A6 07 ldx PARAM1 ; Start with top edge +0083C3 2 +0083C3 2 WGFancyRect_vertLoop: +0083C3 2 +0083C3 2 DA phx ; We'll need X back for now, but save the line number +0083C4 2 +0083C4 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect +0083C7 2 85 28 sta BASL +0083C9 2 BD D7 94 lda TEXTLINES_H,x +0083CC 2 85 29 sta BASH +0083CE 2 +0083CE 2 A5 06 lda PARAM0 +0083D0 2 3A dec +0083D1 2 4A lsr +0083D2 2 18 clc +0083D3 2 65 28 adc BASL +0083D5 2 85 28 sta BASL +0083D7 2 A9 00 lda #$0 +0083D9 2 65 29 adc BASH +0083DB 2 85 29 sta BASH +0083DD 2 +0083DD 2 A5 06 lda PARAM0 ; Left edge even? +0083DF 2 3A dec +0083E0 2 29 01 and #$01 +0083E2 2 D0 38 bne WGFancyRect_vertLoopOdd +0083E4 2 +0083E4 2 ; CASE 1: Left edge even-aligned, even width +0083E4 2 8D 55 C0 SETSWITCH PAGE2ON +0083E7 2 A0 00 ldy #$0 +0083E9 2 A9 5A lda #FR_LEFT ; Plot the left edge +0083EB 2 91 28 sta (BASL),y +0083ED 2 +0083ED 2 A5 08 lda PARAM2 ; Is width even? +0083EF 2 1A inc +0083F0 2 1A inc +0083F1 2 29 01 and #$01 +0083F3 2 D0 11 bne WGFancyRect_vertLoopEvenAlignedOddWidth +0083F5 2 +0083F5 2 A5 08 lda PARAM2 ; Calculate right edge +0083F7 2 1A inc +0083F8 2 1A inc +0083F9 2 4A lsr +0083FA 2 3A dec +0083FB 2 A8 tay +0083FC 2 8D 54 C0 SETSWITCH PAGE2OFF +0083FF 2 A9 5A lda #FR_RIGHT ; Plot the right edge +008401 2 91 28 sta (BASL),y +008403 2 4C 13 84 jmp WGFancyRect_vertLoopEvenAlignedNextRow +008406 2 +008406 2 WGFancyRect_vertLoopEvenAlignedOddWidth: +008406 2 ; CASE 1a: Left edge even-aligned, odd width +008406 2 8D 55 C0 SETSWITCH PAGE2ON +008409 2 A5 08 lda PARAM2 ; Calculate right edge +00840B 2 1A inc +00840C 2 1A inc +00840D 2 4A lsr +00840E 2 A8 tay +00840F 2 A9 5A lda #FR_RIGHT ; Plot the right edge +008411 2 91 28 sta (BASL),y +008413 2 +008413 2 WGFancyRect_vertLoopEvenAlignedNextRow: +008413 2 FA plx ; Prepare for next row +008414 2 E8 inx +008415 2 E4 19 cpx SCRATCH0 +008417 2 D0 AA bne WGFancyRect_vertLoop +008419 2 4C 56 84 jmp WGFancyRect_corners +00841C 2 +00841C 2 +00841C 2 WGFancyRect_vertLoopOdd: +00841C 2 ; CASE 2: Left edge odd-aligned, even width +00841C 2 8D 54 C0 SETSWITCH PAGE2OFF +00841F 2 A0 00 ldy #$0 +008421 2 A9 5A lda #FR_LEFT ; Plot the left edge +008423 2 91 28 sta (BASL),y +008425 2 +008425 2 A5 08 lda PARAM2 ; Is width even? +008427 2 1A inc +008428 2 1A inc +008429 2 29 01 and #$01 +00842B 2 D0 10 bne WGFancyRect_vertLoopOddAlignedOddWidth +00842D 2 +00842D 2 A5 08 lda PARAM2 ; Calculate right edge +00842F 2 1A inc +008430 2 1A inc +008431 2 4A lsr +008432 2 A8 tay +008433 2 8D 55 C0 SETSWITCH PAGE2ON +008436 2 A9 5A lda #FR_RIGHT ; Plot the right edge +008438 2 91 28 sta (BASL),y +00843A 2 4C 4A 84 jmp WGFancyRect_vertLoopOddAlignedNextRow +00843D 2 +00843D 2 WGFancyRect_vertLoopOddAlignedOddWidth: +00843D 2 ; CASE 2a: Left edge odd-aligned, odd width +00843D 2 8D 54 C0 SETSWITCH PAGE2OFF +008440 2 A5 08 lda PARAM2 ; Calculate right edge +008442 2 1A inc +008443 2 1A inc +008444 2 4A lsr +008445 2 A8 tay +008446 2 A9 5A lda #FR_RIGHT ; Plot the right edge +008448 2 91 28 sta (BASL),y +00844A 2 +00844A 2 WGFancyRect_vertLoopOddAlignedNextRow: +00844A 2 FA plx ; Prepare for next row +00844B 2 E8 inx +00844C 2 E4 19 cpx SCRATCH0 +00844E 2 D0 03 bne WGFancyRect_vertLoopJmp +008450 2 4C 56 84 jmp WGFancyRect_corners +008453 2 WGFancyRect_vertLoopJmp: +008453 2 4C C3 83 jmp WGFancyRect_vertLoop +008456 2 +008456 2 WGFancyRect_corners: +008456 2 A5 06 lda PARAM0 ; Top left corner +008458 2 3A dec +008459 2 8D C9 92 sta WG_CURSORX +00845C 2 A5 07 lda PARAM1 +00845E 2 3A dec +00845F 2 8D CA 92 sta WG_CURSORY +008462 2 A9 5A lda #FR_TOPLEFT +008464 2 20 55 7F jsr WGPlot +008467 2 +008467 2 A5 06 lda PARAM0 ; Top right corner +008469 2 18 clc +00846A 2 65 08 adc PARAM2 +00846C 2 8D C9 92 sta WG_CURSORX +00846F 2 A9 5E lda #FR_TOPRIGHT +008471 2 20 55 7F jsr WGPlot +008474 2 +008474 2 EE CA 92 inc WG_CURSORY +008477 2 A9 52 lda #FR_TOPRIGHTA +008479 2 20 55 7F jsr WGPlot +00847C 2 +00847C 2 A5 07 lda PARAM1 ; Bottom right corner +00847E 2 3A dec +00847F 2 18 clc +008480 2 65 09 adc PARAM3 +008482 2 8D CA 92 sta WG_CURSORY +008485 2 A9 51 lda #FR_BOTTOMRIGHTA1 +008487 2 20 55 7F jsr WGPlot +00848A 2 +00848A 2 EE CA 92 inc WG_CURSORY +00848D 2 A9 7F lda #FR_BOTTOMRIGHT +00848F 2 20 55 7F jsr WGPlot +008492 2 +008492 2 CE C9 92 dec WG_CURSORX +008495 2 A9 50 lda #FR_BOTTOMRIGHTA2 +008497 2 20 55 7F jsr WGPlot +00849A 2 +00849A 2 A5 06 lda PARAM0 ; Bottom left corner +00849C 2 8D C9 92 sta WG_CURSORX +00849F 2 A9 4F lda #FR_BOTTOMLEFTA +0084A1 2 20 55 7F jsr WGPlot +0084A4 2 CE C9 92 dec WG_CURSORX +0084A7 2 A9 5A lda #FR_BOTTOMLEFT +0084A9 2 20 55 7F jsr WGPlot +0084AC 2 +0084AC 2 WGFancyRect_done: +0084AC 2 8D 54 C0 SETSWITCH PAGE2OFF +0084AF 2 68 85 1A 68 RESTORE_ZPS +0084B3 2 85 19 +0084B5 2 7A FA 68 RESTORE_AXY +0084B8 2 60 rts +0084B9 2 +0084B9 2 +0084B9 1 .include "views.s" +0084B9 2 ; +0084B9 2 ; views.s +0084B9 2 ; Management routines for GUI views +0084B9 2 ; +0084B9 2 ; Created by Quinn Dunki on 8/15/14. +0084B9 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +0084B9 2 ; +0084B9 2 +0084B9 2 +0084B9 2 WG_FEATURE_UP = %00010000 +0084B9 2 WG_FEATURE_DN = %00100000 +0084B9 2 WG_FEATURE_LF = %00110000 +0084B9 2 WG_FEATURE_RT = %01000000 +0084B9 2 +0084B9 2 +0084B9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0084B9 2 ; WGCreateView +0084B9 2 ; Creates and selects a new view +0084B9 2 ; PARAM0: Pointer to configuration struct (LSB) +0084B9 2 ; PARAM1: Pointer to configuration struct (MSB) +0084B9 2 ; +0084B9 2 ; Configuration struct: +0084B9 2 ; ID: View ID (0-f) +0084B9 2 ; ST: Style +0084B9 2 ; XX: Screen X origin +0084B9 2 ; YY: Screen Y origin +0084B9 2 ; SW: Screen width +0084B9 2 ; SH: Screen height +0084B9 2 ; VW: View Width +0084B9 2 ; VH: View Height +0084B9 2 ; +0084B9 2 WGCreateView: +0084B9 2 48 DA 5A SAVE_AXY +0084BC 2 +0084BC 2 A0 00 ldy #0 +0084BE 2 B1 06 lda (PARAM0),y ; Find our new view record +0084C0 2 48 pha ; Cache view ID so we can select when we're done +0084C1 2 +0084C1 2 0A asl +0084C2 2 0A asl +0084C3 2 0A asl +0084C4 2 0A asl ; Records are 8 bytes wide +0084C5 2 AA tax +0084C6 2 +0084C6 2 C8 iny +0084C7 2 B1 06 lda (PARAM0),y +0084C9 2 48 pha ; Cache style byte for later +0084CA 2 +0084CA 2 C8 iny +0084CB 2 B1 06 lda (PARAM0),y +0084CD 2 9D D6 92 sta WG_VIEWRECORDS+0,x ; Screen X +0084D0 2 +0084D0 2 C8 iny +0084D1 2 B1 06 lda (PARAM0),y +0084D3 2 9D D7 92 sta WG_VIEWRECORDS+1,x ; Screen Y +0084D6 2 +0084D6 2 C8 iny +0084D7 2 B1 06 lda (PARAM0),y +0084D9 2 9D D8 92 sta WG_VIEWRECORDS+2,x ; Screen Width +0084DC 2 +0084DC 2 C8 iny +0084DD 2 B1 06 lda (PARAM0),y +0084DF 2 9D D9 92 sta WG_VIEWRECORDS+3,x ; Screen Height +0084E2 2 +0084E2 2 68 pla +0084E3 2 9D DA 92 sta WG_VIEWRECORDS+4,x ; Style +0084E6 2 +0084E6 2 9E DB 92 stz WG_VIEWRECORDS+5,x ; Initialize scrolling +0084E9 2 9E DC 92 stz WG_VIEWRECORDS+6,x +0084EC 2 +0084EC 2 C8 iny +0084ED 2 B1 06 lda (PARAM0),y +0084EF 2 9D DD 92 sta WG_VIEWRECORDS+7,x ; View Width +0084F2 2 +0084F2 2 C8 iny +0084F3 2 B1 06 lda (PARAM0),y +0084F5 2 9D DE 92 sta WG_VIEWRECORDS+8,x ; View Height +0084F8 2 +0084F8 2 9E DF 92 stz WG_VIEWRECORDS+9,x ; Initialize state +0084FB 2 9E E0 92 stz WG_VIEWRECORDS+10,x ; Initialize callback +0084FE 2 9E E1 92 stz WG_VIEWRECORDS+11,x +008501 2 9E E2 92 stz WG_VIEWRECORDS+12,x ; Initialize title +008504 2 9E E3 92 stz WG_VIEWRECORDS+13,x +008507 2 +008507 2 68 pla +008508 2 20 57 87 jsr WGSelectView ; Leave this as the active view +00850B 2 +00850B 2 WGCreateView_done: +00850B 2 7A FA 68 RESTORE_AXY +00850E 2 60 rts +00850F 2 +00850F 2 +00850F 2 +00850F 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00850F 2 ; WGCreateCheckbox +00850F 2 ; Creates a new checkbox +00850F 2 ; PARAM0: Pointer to configuration struct (LSB) +00850F 2 ; PARAM1: Pointer to configuration struct (MSB) +00850F 2 ; +00850F 2 ; Configuration struct: +00850F 2 ; ID: View ID (0-f) +00850F 2 ; XX: Screen X origin +00850F 2 ; YY: Screen Y origin +00850F 2 ; SL: String pointer (LSB) +00850F 2 ; SH: String pointer (MSB) +00850F 2 ; +00850F 2 WGCreateCheckbox: +00850F 2 48 DA 5A SAVE_AXY +008512 2 +008512 2 A0 00 ldy #0 +008514 2 B1 06 lda (PARAM0),y ; Find our new view record +008516 2 48 pha ; Cache view ID so we can select when we're done +008517 2 +008517 2 0A asl +008518 2 0A asl +008519 2 0A asl +00851A 2 0A asl ; Records are 16 bytes wide +00851B 2 AA tax +00851C 2 +00851C 2 C8 iny +00851D 2 B1 06 lda (PARAM0),y +00851F 2 9D D6 92 sta WG_VIEWRECORDS+0,x ; Screen X +008522 2 +008522 2 C8 iny +008523 2 B1 06 lda (PARAM0),y +008525 2 9D D7 92 sta WG_VIEWRECORDS+1,x ; Screen Y +008528 2 +008528 2 A9 01 lda #1 +00852A 2 9D D8 92 sta WG_VIEWRECORDS+2,x ; Initialize screen width +00852D 2 9D D9 92 sta WG_VIEWRECORDS+3,x ; Initialize screen height +008530 2 9D DD 92 sta WG_VIEWRECORDS+7,x ; Initialize view width +008533 2 9D DE 92 sta WG_VIEWRECORDS+8,x ; Initialize view height +008536 2 +008536 2 A9 02 lda #VIEW_STYLE_CHECK +008538 2 9D DA 92 sta WG_VIEWRECORDS+4,x ; Style +00853B 2 +00853B 2 9E DB 92 stz WG_VIEWRECORDS+5,x ; Initialize scrolling +00853E 2 9E DC 92 stz WG_VIEWRECORDS+6,x +008541 2 +008541 2 9E DF 92 stz WG_VIEWRECORDS+9,x ; Initialize state +008544 2 9E E0 92 stz WG_VIEWRECORDS+10,x ; Initialize callback +008547 2 9E E1 92 stz WG_VIEWRECORDS+11,x +00854A 2 +00854A 2 C8 iny +00854B 2 B1 06 lda (PARAM0),y +00854D 2 9D E2 92 sta WG_VIEWRECORDS+12,x ; Title +008550 2 C8 iny +008551 2 B1 06 lda (PARAM0),y +008553 2 9D E3 92 sta WG_VIEWRECORDS+13,x +008556 2 +008556 2 68 pla +008557 2 20 57 87 jsr WGSelectView ; Leave this as the active view +00855A 2 +00855A 2 WGCreateCheckbox_done: +00855A 2 7A FA 68 RESTORE_AXY +00855D 2 60 rts +00855E 2 +00855E 2 +00855E 2 +00855E 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00855E 2 ; WGCreateButton +00855E 2 ; Creates a new button +00855E 2 ; PARAM0: Pointer to configuration struct (LSB) +00855E 2 ; PARAM1: Pointer to configuration struct (MSB) +00855E 2 ; +00855E 2 ; Configuration struct: +00855E 2 ; ID: View ID (0-f) +00855E 2 ; XX: Screen X origin +00855E 2 ; YY: Screen Y origin +00855E 2 ; BW: Button width +00855E 2 ; PL: Action callback (LSB) +00855E 2 ; PH: Action callback (MSB) +00855E 2 ; SL: Title string pointer (LSB) +00855E 2 ; SH: Title string pointer (MSB) +00855E 2 WGCreateButton: +00855E 2 48 DA 5A SAVE_AXY +008561 2 +008561 2 A0 00 ldy #0 +008563 2 B1 06 lda (PARAM0),y ; Find our new view record +008565 2 48 pha ; Cache view ID so we can select when we're done +008566 2 +008566 2 0A asl +008567 2 0A asl +008568 2 0A asl +008569 2 0A asl ; Records are 16 bytes wide +00856A 2 AA tax +00856B 2 +00856B 2 C8 iny +00856C 2 B1 06 lda (PARAM0),y +00856E 2 9D D6 92 sta WG_VIEWRECORDS+0,x ; Screen X +008571 2 +008571 2 C8 iny +008572 2 B1 06 lda (PARAM0),y +008574 2 9D D7 92 sta WG_VIEWRECORDS+1,x ; Screen Y +008577 2 +008577 2 C8 iny +008578 2 B1 06 lda (PARAM0),y +00857A 2 9D D8 92 sta WG_VIEWRECORDS+2,x ; Screen width +00857D 2 9D DD 92 sta WG_VIEWRECORDS+7,x ; View width +008580 2 +008580 2 A9 01 lda #1 +008582 2 9D D9 92 sta WG_VIEWRECORDS+3,x ; Initialize screen height +008585 2 9D DE 92 sta WG_VIEWRECORDS+8,x ; Initialize view height +008588 2 +008588 2 A9 03 lda #VIEW_STYLE_BUTTON +00858A 2 9D DA 92 sta WG_VIEWRECORDS+4,x ; Style +00858D 2 +00858D 2 9E DB 92 stz WG_VIEWRECORDS+5,x ; Initialize scrolling +008590 2 9E DC 92 stz WG_VIEWRECORDS+6,x +008593 2 9E DF 92 stz WG_VIEWRECORDS+9,x ; Initialize state +008596 2 +008596 2 C8 iny +008597 2 B1 06 lda (PARAM0),y +008599 2 9D E0 92 sta WG_VIEWRECORDS+10,x ; Callback +00859C 2 C8 iny +00859D 2 B1 06 lda (PARAM0),y +00859F 2 9D E1 92 sta WG_VIEWRECORDS+11,x +0085A2 2 +0085A2 2 C8 iny +0085A3 2 B1 06 lda (PARAM0),y +0085A5 2 9D E2 92 sta WG_VIEWRECORDS+12,x ; Title +0085A8 2 C8 iny +0085A9 2 B1 06 lda (PARAM0),y +0085AB 2 9D E3 92 sta WG_VIEWRECORDS+13,x +0085AE 2 +0085AE 2 68 pla +0085AF 2 20 57 87 jsr WGSelectView ; Leave this as the active view +0085B2 2 +0085B2 2 WGCreateButton_done: +0085B2 2 7A FA 68 RESTORE_AXY +0085B5 2 60 rts +0085B6 2 +0085B6 2 +0085B6 2 +0085B6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0085B6 2 ; WGPaintView +0085B6 2 ; Paints the current view +0085B6 2 ; +0085B6 2 WGPaintView: +0085B6 2 48 DA 5A SAVE_AXY +0085B9 2 A5 06 48 A5 SAVE_ZPP +0085BD 2 07 48 A5 08 +0085C1 2 48 A5 09 48 +0085C5 2 +0085C5 2 AD CD 92 0A LDY_ACTIVEVIEW +0085C9 2 0A 0A 0A A8 +0085CD 2 +0085CD 2 B9 DA 92 lda WG_VIEWRECORDS+4,y ; Cache style information +0085D0 2 29 0F and #$f ; Mask off flag bits +0085D2 2 48 pha +0085D3 2 +0085D3 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Fetch the geometry +0085D6 2 85 06 sta PARAM0 +0085D8 2 B9 D7 92 lda WG_VIEWRECORDS+1,y +0085DB 2 85 07 sta PARAM1 +0085DD 2 B9 D8 92 lda WG_VIEWRECORDS+2,y +0085E0 2 85 08 sta PARAM2 +0085E2 2 B9 D9 92 lda WG_VIEWRECORDS+3,y +0085E5 2 85 09 sta PARAM3 +0085E7 2 +0085E7 2 68 pla ; Draw outline +0085E8 2 C9 01 cmp #VIEW_STYLE_FANCY +0085EA 2 F0 0D beq WGPaintView_decorated +0085EC 2 +0085EC 2 20 24 81 jsr WGStrokeRect +0085EF 2 +0085EF 2 C9 02 cmp #VIEW_STYLE_CHECK +0085F1 2 F0 0E beq WGPaintView_check +0085F3 2 C9 03 cmp #VIEW_STYLE_BUTTON +0085F5 2 F0 0F beq WGPaintView_button +0085F7 2 80 10 bra WGPaintView_done +0085F9 2 +0085F9 2 WGPaintView_decorated: +0085F9 2 20 15 83 jsr WGFancyRect +0085FC 2 20 DC 86 jsr paintWindowTitle +0085FF 2 80 08 bra WGPaintView_done +008601 2 +008601 2 WGPaintView_check: +008601 2 20 19 86 jsr paintCheck +008604 2 80 03 bra WGPaintView_done +008606 2 +008606 2 WGPaintView_button: +008606 2 20 71 86 jsr paintButton +008609 2 +008609 2 WGPaintView_done: +008609 2 68 85 09 68 RESTORE_ZPP +00860D 2 85 08 68 85 +008611 2 07 68 85 06 +008615 2 7A FA 68 RESTORE_AXY +008618 2 60 rts +008619 2 +008619 2 +008619 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008619 2 ; paintCheck +008619 2 ; Paints the contents of a checkbox +008619 2 ; Y: Index into view records of checkbox to paint +008619 2 ; Side effects: Clobbers all registers,P0,P1 +008619 2 paintCheck: +008619 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Position cursor +00861C 2 8D C9 92 sta WG_CURSORX +00861F 2 B9 D7 92 lda WG_VIEWRECORDS+1,y +008622 2 8D CA 92 sta WG_CURSORY +008625 2 +008625 2 B9 DF 92 lda WG_VIEWRECORDS+9,y ; Determine our visual state +008628 2 29 80 and #$80 +00862A 2 D0 0F bne paintCheck_selected +00862C 2 +00862C 2 B9 DF 92 lda WG_VIEWRECORDS+9,y +00862F 2 29 01 and #$01 +008631 2 F0 04 beq paintCheck_unselectedUnchecked +008633 2 +008633 2 A9 44 lda #'D' +008635 2 80 11 bra paintCheck_plot +008637 2 +008637 2 paintCheck_unselectedUnchecked: +008637 2 A9 A0 lda #' '+$80 +008639 2 80 0D bra paintCheck_plot +00863B 2 +00863B 2 paintCheck_selected: +00863B 2 B9 DF 92 lda WG_VIEWRECORDS+9,y +00863E 2 29 01 and #$01 +008640 2 F0 04 beq paintCheck_selectedUnchecked +008642 2 +008642 2 A9 45 lda #'E' +008644 2 80 02 bra paintCheck_plot +008646 2 +008646 2 paintCheck_selectedUnchecked: +008646 2 A9 20 lda #' ' +008648 2 +008648 2 paintCheck_plot: ; Paint our state +008648 2 20 55 7F jsr WGPlot +00864B 2 +00864B 2 EE C9 92 inc WG_CURSORX ; Prepare for title +00864E 2 EE C9 92 inc WG_CURSORX +008651 2 A9 FF lda #CHAR_NORMAL +008653 2 85 32 sta INVERSE +008655 2 +008655 2 B9 E2 92 lda WG_VIEWRECORDS+12,y +008658 2 85 06 sta PARAM0 +00865A 2 B9 E3 92 lda WG_VIEWRECORDS+13,y +00865D 2 85 07 sta PARAM1 +00865F 2 A0 00 ldy #0 +008661 2 +008661 2 paintCheck_titleLoop: +008661 2 B1 06 lda (PARAM0),y +008663 2 F0 0B beq paintCheck_done +008665 2 09 80 ora #$80 +008667 2 20 55 7F jsr WGPlot +00866A 2 EE C9 92 inc WG_CURSORX +00866D 2 C8 iny +00866E 2 80 F1 bra paintCheck_titleLoop +008670 2 +008670 2 paintCheck_done: +008670 2 60 rts +008671 2 +008671 2 +008671 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008671 2 ; paintButton +008671 2 ; Paints the contents of a button +008671 2 ; Y: Index into view records of button to paint +008671 2 ; Side effects: Clobbers all registers,P0,P1,S1 +008671 2 paintButton: +008671 2 B9 E2 92 lda WG_VIEWRECORDS+12,y ; Prep the title string +008674 2 85 06 sta PARAM0 +008676 2 B9 E3 92 lda WG_VIEWRECORDS+13,y +008679 2 85 07 sta PARAM1 +00867B 2 +00867B 2 20 AC 7E jsr WGStrLen ; Compute centering offset for title +00867E 2 4A lsr +00867F 2 85 1A sta SCRATCH1 +008681 2 B9 D8 92 lda WG_VIEWRECORDS+2,y +008684 2 4A lsr +008685 2 38 sec +008686 2 E5 1A sbc SCRATCH1 +008688 2 85 1A sta SCRATCH1 ; Cache this for left margin rendering +00868A 2 +00868A 2 A9 00 lda #0 ; Position and print title +00868C 2 8D CB 92 sta WG_LOCALCURSORX +00868F 2 A9 00 lda #0 +008691 2 8D CC 92 sta WG_LOCALCURSORY +008694 2 20 69 89 jsr WGSyncGlobalCursor +008697 2 +008697 2 B9 DF 92 lda WG_VIEWRECORDS+9,y ; Is button highlighted? +00869A 2 29 80 and #$80 +00869C 2 D0 08 bne paintButton_titleSelected +00869E 2 A9 FF lda #CHAR_NORMAL +0086A0 2 85 32 sta INVERSE +0086A2 2 A9 A0 lda #' '+$80 +0086A4 2 80 06 bra paintButton_titleMarginLeft +0086A6 2 +0086A6 2 paintButton_titleSelected: +0086A6 2 A9 3F lda #CHAR_INVERSE +0086A8 2 85 32 sta INVERSE +0086AA 2 A9 20 lda #' ' +0086AC 2 +0086AC 2 paintButton_titleMarginLeft: +0086AC 2 A2 00 ldx #0 +0086AE 2 +0086AE 2 paintButton_titleMarginLeftLoop: +0086AE 2 E4 1A cpx SCRATCH1 +0086B0 2 B0 0D bcs paintButton_title ; Left margin finished +0086B2 2 20 55 7F jsr WGPlot +0086B5 2 EE C9 92 inc WG_CURSORX +0086B8 2 EE CB 92 inc WG_LOCALCURSORX +0086BB 2 E8 inx +0086BC 2 4C AE 86 jmp paintButton_titleMarginLeftLoop +0086BF 2 +0086BF 2 paintButton_title: +0086BF 2 20 90 7F jsr WGPrint +0086C2 2 BE D8 92 ldx WG_VIEWRECORDS+2,y +0086C5 2 86 1A stx SCRATCH1 ; Loop until right edge of button is reached +0086C7 2 AE CB 92 ldx WG_LOCALCURSORX +0086CA 2 +0086CA 2 paintButton_titleMarginRightLoop: +0086CA 2 E4 1A cpx SCRATCH1 +0086CC 2 B0 0D bcs paintButton_done ; Right margin finished +0086CE 2 20 55 7F jsr WGPlot +0086D1 2 EE C9 92 inc WG_CURSORX +0086D4 2 EE CB 92 inc WG_LOCALCURSORX +0086D7 2 E8 inx +0086D8 2 4C CA 86 jmp paintButton_titleMarginRightLoop +0086DB 2 +0086DB 2 paintButton_done: +0086DB 2 60 rts +0086DC 2 +0086DC 2 +0086DC 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0086DC 2 ; paintWindowTitle +0086DC 2 ; Paints the title of a fancy window +0086DC 2 ; Y: Index into view records of view title to paint +0086DC 2 ; Side effects: Clobbers all registers,P0,P1,S1 +0086DC 2 paintWindowTitle: +0086DC 2 B9 E2 92 lda WG_VIEWRECORDS+12,y ; Prep the title string +0086DF 2 85 06 sta PARAM0 +0086E1 2 B9 E3 92 lda WG_VIEWRECORDS+13,y +0086E4 2 85 07 sta PARAM1 +0086E6 2 D0 04 bne paintWindowTitle_compute +0086E8 2 +0086E8 2 paintWindowTitle_checkNull: +0086E8 2 A5 06 lda PARAM0 +0086EA 2 F0 29 beq paintWindowTitle_done +0086EC 2 +0086EC 2 paintWindowTitle_compute: +0086EC 2 20 AC 7E jsr WGStrLen ; Compute centering offset for title +0086EF 2 4A lsr +0086F0 2 85 1A sta SCRATCH1 +0086F2 2 B9 D8 92 lda WG_VIEWRECORDS+2,y +0086F5 2 4A lsr +0086F6 2 38 sec +0086F7 2 E5 1A sbc SCRATCH1 +0086F9 2 8D CB 92 sta WG_LOCALCURSORX ; Position cursor +0086FC 2 A9 FF lda #-1 +0086FE 2 8D CC 92 sta WG_LOCALCURSORY +008701 2 20 69 89 jsr WGSyncGlobalCursor +008704 2 +008704 2 A0 00 ldy #0 +008706 2 paintWindowTitleLoop: +008706 2 B1 06 lda (PARAM0),y +008708 2 F0 0B beq paintWindowTitle_done +00870A 2 09 80 ora #%10000000 +00870C 2 20 55 7F jsr WGPlot ; Draw the character +00870F 2 C8 iny +008710 2 EE C9 92 inc WG_CURSORX ; Advance cursors +008713 2 80 F1 bra paintWindowTitleLoop +008715 2 +008715 2 paintWindowTitle_done: +008715 2 60 rts +008716 2 +008716 2 +008716 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008716 2 ; WGEraseViewContents +008716 2 ; Erases the contents of the current view (interior contents only) +008716 2 ; +008716 2 WGEraseViewContents: +008716 2 48 5A SAVE_AY +008718 2 A5 06 48 A5 SAVE_ZPP +00871C 2 07 48 A5 08 +008720 2 48 A5 09 48 +008724 2 +008724 2 AD CD 92 0A LDY_ACTIVEVIEW +008728 2 0A 0A 0A A8 +00872C 2 +00872C 2 B9 D6 92 lda WG_VIEWRECORDS,y ; Fetch the record +00872F 2 85 06 sta PARAM0 +008731 2 C8 iny +008732 2 B9 D6 92 lda WG_VIEWRECORDS,y +008735 2 85 07 sta PARAM1 +008737 2 C8 iny +008738 2 B9 D6 92 lda WG_VIEWRECORDS,y +00873B 2 85 08 sta PARAM2 +00873D 2 C8 iny +00873E 2 B9 D6 92 lda WG_VIEWRECORDS,y +008741 2 85 09 sta PARAM3 +008743 2 +008743 2 A0 A0 ldy #' '+$80 +008745 2 20 98 80 jsr WGFillRect +008748 2 +008748 2 WGEraseViewContents_done: +008748 2 68 85 09 68 RESTORE_ZPP +00874C 2 85 08 68 85 +008750 2 07 68 85 06 +008754 2 7A 68 RESTORE_AY +008756 2 60 rts +008757 2 +008757 2 +008757 2 +008757 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008757 2 ; WGSelectView +008757 2 ; Selects the active view +008757 2 ; A: ID +008757 2 ; +008757 2 WGSelectView: +008757 2 8D CD 92 sta WG_ACTIVEVIEW +00875A 2 +00875A 2 ; Initialize cursor to local origin +00875A 2 9C CB 92 stz WG_LOCALCURSORX +00875D 2 9C CC 92 stz WG_LOCALCURSORY +008760 2 +008760 2 20 2B 8B jsr cacheClipPlanes ; View changed, so clipping cache is stale +008763 2 +008763 2 WGSelectView_done: +008763 2 60 rts +008764 2 +008764 2 +008764 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008764 2 ; WGViewFocus +008764 2 ; Shifts focus to the selected view +008764 2 ; Side effects: Changes selected view, repaints some views +008764 2 ; +008764 2 WGViewFocus: +008764 2 48 5A SAVE_AY +008766 2 +008766 2 AD CD 92 lda WG_ACTIVEVIEW ; Stash current selection +008769 2 48 pha +00876A 2 +00876A 2 20 EB 87 jsr unfocusCurrent +00876D 2 +00876D 2 68 pla +00876E 2 8D CE 92 sta WG_FOCUSVIEW ; Focus on our current selection +008771 2 20 0A 88 jsr focusCurrent +008774 2 +008774 2 7A 68 RESTORE_AY +008776 2 60 rts +008777 2 +008777 2 +008777 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008777 2 ; WGViewUnfocus +008777 2 ; Unfocuses all views +008777 2 ; Side effects: Changes selected view, repaints some views +008777 2 ; +008777 2 WGViewUnfocus: +008777 2 48 pha +008778 2 +008778 2 20 EB 87 jsr unfocusCurrent +00877B 2 +00877B 2 A9 FF lda #$ff +00877D 2 8D CE 92 sta WG_FOCUSVIEW +008780 2 +008780 2 WGViewUnfocus_done: +008780 2 68 pla +008781 2 60 rts +008782 2 +008782 2 +008782 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008782 2 ; WGViewFocusNext +008782 2 ; Shifts focus to the next view +008782 2 ; Side effects: Changes selected view, repaints some views +008782 2 ; +008782 2 WGViewFocusNext: +008782 2 48 5A SAVE_AY +008784 2 +008784 2 20 EB 87 jsr unfocusCurrent +008787 2 +008787 2 WGViewFocusNext_loop: +008787 2 EE CE 92 inc WG_FOCUSVIEW ; Increment and wrap +00878A 2 AD CE 92 0A LDY_FOCUSVIEW +00878E 2 0A 0A 0A A8 +008792 2 B9 D8 92 lda WG_VIEWRECORDS+2,y +008795 2 D0 05 bne WGViewFocusNext_wantFocus +008797 2 A9 00 lda #0 +008799 2 8D CE 92 sta WG_FOCUSVIEW +00879C 2 +00879C 2 WGViewFocusNext_wantFocus: ; Does this view accept focus? +00879C 2 AD CE 92 0A LDY_FOCUSVIEW +0087A0 2 0A 0A 0A A8 +0087A4 2 B9 DA 92 lda WG_VIEWRECORDS+4,y +0087A7 2 29 0F and #$f ; Mask off flag bits +0087A9 2 C9 02 cmp #VIEW_STYLE_TAKESFOCUS +0087AB 2 90 DA bcc WGViewFocusNext_loop +0087AD 2 +0087AD 2 WGViewFocusNext_focus: +0087AD 2 20 0A 88 jsr focusCurrent +0087B0 2 +0087B0 2 7A 68 RESTORE_AY +0087B2 2 60 rts +0087B3 2 +0087B3 2 +0087B3 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0087B3 2 ; WGViewFocusPrev +0087B3 2 ; Shifts focus to the prev view +0087B3 2 ; Side effects: Changes selected view, repaints some views +0087B3 2 ; +0087B3 2 WGViewFocusPrev: +0087B3 2 48 DA 5A SAVE_AXY +0087B6 2 +0087B6 2 20 EB 87 jsr unfocusCurrent +0087B9 2 +0087B9 2 WGViewFocusPrev_loop: +0087B9 2 CE CE 92 dec WG_FOCUSVIEW ; Decrement and wrap +0087BC 2 10 15 bpl WGViewFocusPrev_wantFocus +0087BE 2 +0087BE 2 WGViewFocusPrev_hadNone: +0087BE 2 A2 0F ldx #$f +0087C0 2 WGViewFocusPrev_findEndLoop: +0087C0 2 8E CE 92 stx WG_FOCUSVIEW +0087C3 2 AD CE 92 0A LDY_FOCUSVIEW +0087C7 2 0A 0A 0A A8 +0087CB 2 B9 D8 92 lda WG_VIEWRECORDS+2,y +0087CE 2 D0 03 bne WGViewFocusPrev_wantFocus +0087D0 2 CA dex +0087D1 2 80 ED bra WGViewFocusPrev_findEndLoop +0087D3 2 +0087D3 2 WGViewFocusPrev_wantFocus: ; Does this view accept focus? +0087D3 2 AD CE 92 0A LDY_FOCUSVIEW +0087D7 2 0A 0A 0A A8 +0087DB 2 B9 DA 92 lda WG_VIEWRECORDS+4,y +0087DE 2 29 0F and #$f ; Mask off flag bits +0087E0 2 C9 02 cmp #VIEW_STYLE_TAKESFOCUS +0087E2 2 90 D5 bcc WGViewFocusPrev_loop +0087E4 2 +0087E4 2 WGViewFocusPrev_focus: +0087E4 2 20 0A 88 jsr focusCurrent +0087E7 2 +0087E7 2 7A FA 68 RESTORE_AXY +0087EA 2 60 rts +0087EB 2 +0087EB 2 +0087EB 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0087EB 2 ; unfocusCurrent +0087EB 2 ; Unfocuses current view, if any +0087EB 2 ; Side effects: Clobbers A, +0087EB 2 ; Leaves Y pointed at current focus view record +0087EB 2 ; Changes active view selection +0087EB 2 unfocusCurrent: +0087EB 2 AD CE 92 lda WG_FOCUSVIEW +0087EE 2 30 19 bmi unfocusCurrentDone ; No current focus +0087F0 2 +0087F0 2 AD CE 92 0A LDY_FOCUSVIEW ; Unfocus current view +0087F4 2 0A 0A 0A A8 +0087F8 2 B9 DF 92 lda WG_VIEWRECORDS+9,y +0087FB 2 29 7F and #%01111111 +0087FD 2 99 DF 92 sta WG_VIEWRECORDS+9,y +008800 2 +008800 2 AD CE 92 lda WG_FOCUSVIEW +008803 2 20 57 87 jsr WGSelectView +008806 2 20 B6 85 jsr WGPaintView +008809 2 +008809 2 unfocusCurrentDone: +008809 2 60 rts +00880A 2 +00880A 2 +00880A 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00880A 2 ; focusCurrent +00880A 2 ; Sets focus to desired view, and repaints +00880A 2 ; Side effects: Clobbers A +00880A 2 focusCurrent: +00880A 2 AD CE 92 lda WG_FOCUSVIEW +00880D 2 20 57 87 jsr WGSelectView +008810 2 +008810 2 AD CD 92 0A LDY_ACTIVEVIEW +008814 2 0A 0A 0A A8 +008818 2 +008818 2 B9 DA 92 lda WG_VIEWRECORDS+4,y +00881B 2 29 0F and #$f ; Mask off flag bits +00881D 2 C9 02 cmp #VIEW_STYLE_TAKESFOCUS +00881F 2 90 0B bcc focusCurrent_done +008821 2 +008821 2 B9 DF 92 lda WG_VIEWRECORDS+9,y +008824 2 09 80 ora #%10000000 +008826 2 99 DF 92 sta WG_VIEWRECORDS+9,y +008829 2 +008829 2 20 B6 85 jsr WGPaintView +00882C 2 +00882C 2 focusCurrent_done: +00882C 2 60 rts +00882D 2 +00882D 2 +00882D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00882D 2 ; WGViewFocusAction +00882D 2 ; Performs the action of the focused view +00882D 2 ; WG_GOSUB : Set if the caller should perform an Applesoft GOSUB +00882D 2 ; Side effects: Changes selected view, Repaints some views +00882D 2 ; +00882D 2 WGViewFocusAction: +00882D 2 48 5A SAVE_AY +00882F 2 +00882F 2 AD CE 92 lda WG_FOCUSVIEW +008832 2 30 60 bmi WGViewFocusAction_done +008834 2 +008834 2 AD CE 92 0A LDY_FOCUSVIEW +008838 2 0A 0A 0A A8 +00883C 2 B9 DA 92 lda WG_VIEWRECORDS+4,y ; What kind of view is it? +00883F 2 29 0F and #$f ; Mask off flag bits +008841 2 +008841 2 C9 02 cmp #VIEW_STYLE_CHECK +008843 2 F0 02 beq WGViewFocusAction_toggleCheckbox +008845 2 80 11 bra WGViewFocusAction_buttonClick ; Everything else treated like a button +008847 2 +008847 2 WGViewFocusAction_toggleCheckbox: +008847 2 B9 DF 92 lda WG_VIEWRECORDS+9,y ; Change the checkbox's state and redraw +00884A 2 49 01 eor #%00000001 +00884C 2 99 DF 92 sta WG_VIEWRECORDS+9,y +00884F 2 AD CE 92 lda WG_FOCUSVIEW +008852 2 20 57 87 jsr WGSelectView +008855 2 20 B6 85 jsr WGPaintView +008858 2 ; Fall through so checkboxes can have callbacks too +008858 2 +008858 2 ; NOTE: Self-modifying code ahead! +008858 2 WGViewFocusAction_buttonClick: +008858 2 B9 DA 92 lda WG_VIEWRECORDS+4,y ; Are we an Applesoft button? +00885B 2 29 80 and #VIEW_STYLE_APPLESOFT +00885D 2 D0 13 bne WGViewFocusAction_buttonClickApplesoft +00885F 2 +00885F 2 B9 E1 92 lda WG_VIEWRECORDS+11,y ; Do we have a callback? +008862 2 F0 30 beq WGViewFocusAction_done +008864 2 8D 6F 88 sta WGViewFocusAction_userJSR+2 ; Modify code below so we can JSR to user's code +008867 2 B9 E0 92 lda WG_VIEWRECORDS+10,y +00886A 2 8D 6E 88 sta WGViewFocusAction_userJSR+1 +00886D 2 +00886D 2 WGViewFocusAction_userJSR: +00886D 2 20 94 88 jsr WGViewFocusAction_done ; Overwritten with user's function pointer +008870 2 80 22 bra WGViewFocusAction_done +008872 2 +008872 2 WGViewFocusAction_buttonClickApplesoft: +008872 2 A9 00 lda #0 +008874 2 8D D0 92 sta WG_GOSUB +008877 2 B9 E0 92 lda WG_VIEWRECORDS+10,y ; Do we have a callback? +00887A 2 F0 0E beq WGViewFocusAction_mightBeZero +00887C 2 +00887C 2 WGViewFocusAction_buttonClickApplesoftNotZero: +00887C 2 85 06 sta PARAM0 +00887E 2 B9 E1 92 lda WG_VIEWRECORDS+11,y +008881 2 85 07 sta PARAM1 +008883 2 +008883 2 WGViewFocusAction_buttonClickApplesoftGosub: +008883 2 ; Caller needs to handle Applesoft Gosub, so signal with a flag and return +008883 2 A9 01 lda #1 +008885 2 8D D0 92 sta WG_GOSUB +008888 2 80 0A bra WGViewFocusAction_done +00888A 2 +00888A 2 WGViewFocusAction_mightBeZero: +00888A 2 B9 E1 92 lda WG_VIEWRECORDS+11,y +00888D 2 F0 05 beq WGViewFocusAction_done +00888F 2 B9 E0 92 lda WG_VIEWRECORDS+10,y +008892 2 80 E8 bra WGViewFocusAction_buttonClickApplesoftNotZero +008894 2 +008894 2 WGViewFocusAction_done: +008894 2 7A 68 RESTORE_AY +008896 2 WGViewFocusAction_knownRTS: +008896 2 60 rts +008897 2 +008897 2 +008897 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008897 2 ; WGPendingViewAction +008897 2 ; Performs the action of the pending view, if any +008897 2 ; Global flag set if the caller should perform an Applesoft GOSUB +008897 2 ; Side effects: Changes selected view, Repaints some views +008897 2 ; +008897 2 WGPendingViewAction: +008897 2 48 5A SAVE_AY +008899 2 +008899 2 AD CF 92 lda WG_PENDINGACTIONVIEW +00889C 2 30 3F bmi WGPendingViewAction_done +00889E 2 +00889E 2 29 0F and #$f ; Select view in question +0088A0 2 20 57 87 jsr WGSelectView +0088A3 2 AD CD 92 0A LDY_ACTIVEVIEW +0088A7 2 0A 0A 0A A8 +0088AB 2 +0088AB 2 B9 DA 92 lda WG_VIEWRECORDS+4,y +0088AE 2 29 0F and #$f +0088B0 2 C9 01 cmp #VIEW_STYLE_FANCY ; Filter out fancy views with high-nybble of 0 +0088B2 2 D0 07 bne WGPendingViewAction_chkCallback ; This prevents unnecessary redraws when clicking +0088B4 2 AD CF 92 lda WG_PENDINGACTIONVIEW ; in the content area +0088B7 2 29 F0 and #$f0 +0088B9 2 F0 22 beq WGPendingViewAction_done +0088BB 2 +0088BB 2 WGPendingViewAction_chkCallback: +0088BB 2 ; lda WG_VIEWRECORDS+10,y ; Optimization- only process things that can be clicked +0088BB 2 ; bne WGPendingViewAction_hasCallback +0088BB 2 ; lda WG_VIEWRECORDS+11,y +0088BB 2 ; beq WGPendingViewAction_done +0088BB 2 +0088BB 2 WGPendingViewAction_hasCallback: +0088BB 2 AD CF 92 lda WG_PENDINGACTIONVIEW +0088BE 2 29 F0 and #$f0 ; Check for window features +0088C0 2 F0 4A beq WGPendingViewAction_content +0088C2 2 +0088C2 2 C9 10 cmp #WG_FEATURE_UP +0088C4 2 F0 1F beq WGPendingViewAction_up +0088C6 2 C9 20 cmp #WG_FEATURE_DN +0088C8 2 F0 28 beq WGPendingViewAction_down +0088CA 2 C9 30 cmp #WG_FEATURE_LF +0088CC 2 F0 31 beq WGPendingViewAction_left +0088CE 2 C9 40 cmp #WG_FEATURE_RT +0088D0 2 D0 0B bne WGPendingViewAction_done +0088D2 2 +0088D2 2 A9 FF lda #-1 ; Right arrow +0088D4 2 20 A5 89 jsr WGScrollXBy +0088D7 2 20 64 87 jsr WGViewFocus +0088DA 2 20 2D 88 jsr WGViewFocusAction ; Trigger application to redraw contents +0088DD 2 +0088DD 2 WGPendingViewAction_done: ; Centralized for branch range +0088DD 2 A9 FF lda #$ff +0088DF 2 8D CF 92 sta WG_PENDINGACTIONVIEW +0088E2 2 +0088E2 2 7A 68 RESTORE_AY +0088E4 2 60 rts +0088E5 2 +0088E5 2 WGPendingViewAction_up: +0088E5 2 A9 01 lda #1 ; Up arrow +0088E7 2 20 F9 89 jsr WGScrollYBy +0088EA 2 20 64 87 jsr WGViewFocus +0088ED 2 20 2D 88 jsr WGViewFocusAction ; Trigger application to redraw contents +0088F0 2 80 EB bra WGPendingViewAction_done +0088F2 2 +0088F2 2 WGPendingViewAction_down: +0088F2 2 A9 FF lda #-1 ; Down arrow +0088F4 2 20 F9 89 jsr WGScrollYBy +0088F7 2 20 64 87 jsr WGViewFocus +0088FA 2 20 2D 88 jsr WGViewFocusAction ; Trigger application to redraw contents +0088FD 2 80 DE bra WGPendingViewAction_done +0088FF 2 +0088FF 2 WGPendingViewAction_left: +0088FF 2 A9 01 lda #1 ; Left arrow +008901 2 20 A5 89 jsr WGScrollXBy +008904 2 20 64 87 jsr WGViewFocus +008907 2 20 2D 88 jsr WGViewFocusAction ; Trigger application to redraw contents +00890A 2 80 D1 bra WGPendingViewAction_done +00890C 2 +00890C 2 WGPendingViewAction_content: +00890C 2 20 64 87 jsr WGViewFocus +00890F 2 20 2D 88 jsr WGViewFocusAction +008912 2 20 94 7E jsr delayShort +008915 2 20 77 87 jsr WGViewUnfocus +008918 2 +008918 2 20 14 8D jsr WGPointerDirty ; If we redrew anything, the pointer BG will be stale +00891B 2 80 C0 bra WGPendingViewAction_done +00891D 2 +00891D 2 +00891D 2 +00891D 2 +00891D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00891D 2 ; WGPendingView +00891D 2 ; Returns the view that is currently pending +00891D 2 ; OUT A : Pending view ID, or $ff if none +00891D 2 ; +00891D 2 WGPendingView: +00891D 2 AD CF 92 lda WG_PENDINGACTIONVIEW +008920 2 60 rts +008921 2 +008921 2 +008921 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008921 2 ; WGViewSetTitle +008921 2 ; Sets the title of the active view +008921 2 ; PARAM0: Null-terminated string pointer (LSB) +008921 2 ; PARAM1: Null-terminated string pointer (MSB) +008921 2 WGViewSetTitle: +008921 2 48 5A SAVE_AY +008923 2 +008923 2 AD CD 92 0A LDY_ACTIVEVIEW +008927 2 0A 0A 0A A8 +00892B 2 A5 06 lda PARAM0 +00892D 2 99 E2 92 sta WG_VIEWRECORDS+12,y +008930 2 A5 07 lda PARAM1 +008932 2 99 E3 92 sta WG_VIEWRECORDS+13,y +008935 2 +008935 2 WGViewSetTitle_done: +008935 2 7A 68 RESTORE_AY +008937 2 60 rts +008938 2 +008938 2 +008938 2 +008938 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008938 2 ; WGViewSetAction +008938 2 ; Sets the callback action of the active view +008938 2 ; PARAM0: Null-terminated function pointer (LSB) +008938 2 ; PARAM1: Null-terminated function pointer (MSB) +008938 2 WGViewSetAction: +008938 2 48 5A SAVE_AY +00893A 2 +00893A 2 AD CD 92 0A LDY_ACTIVEVIEW +00893E 2 0A 0A 0A A8 +008942 2 A5 06 lda PARAM0 +008944 2 99 E0 92 sta WG_VIEWRECORDS+10,y +008947 2 A5 07 lda PARAM1 +008949 2 99 E1 92 sta WG_VIEWRECORDS+11,y +00894C 2 +00894C 2 WGViewSetAction_done: +00894C 2 7A 68 RESTORE_AY +00894E 2 60 rts +00894F 2 +00894F 2 +00894F 2 +00894F 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00894F 2 ; WGSetCursor +00894F 2 ; Sets the current local view cursor +00894F 2 ; PARAM0: X +00894F 2 ; PARAM1: Y +00894F 2 ; +00894F 2 WGSetCursor: +00894F 2 48 pha +008950 2 +008950 2 A5 06 lda PARAM0 +008952 2 8D CB 92 sta WG_LOCALCURSORX +008955 2 A5 07 lda PARAM1 +008957 2 8D CC 92 sta WG_LOCALCURSORY +00895A 2 +00895A 2 68 pla +00895B 2 60 rts +00895C 2 +00895C 2 +00895C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00895C 2 ; WGSetGlobalCursor +00895C 2 ; Sets the current global cursor +00895C 2 ; PARAM0: X +00895C 2 ; PARAM1: Y +00895C 2 ; +00895C 2 WGSetGlobalCursor: +00895C 2 48 pha +00895D 2 +00895D 2 A5 06 lda PARAM0 +00895F 2 8D C9 92 sta WG_CURSORX +008962 2 A5 07 lda PARAM1 +008964 2 8D CA 92 sta WG_CURSORY +008967 2 +008967 2 68 pla +008968 2 60 rts +008969 2 +008969 2 +008969 2 +008969 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008969 2 ; WGSyncGlobalCursor +008969 2 ; Synchronizes the global cursor with the current local view's +008969 2 ; cursor +008969 2 ; +008969 2 WGSyncGlobalCursor: +008969 2 48 5A SAVE_AY +00896B 2 +00896B 2 AD CD 92 0A LDY_ACTIVEVIEW +00896F 2 0A 0A 0A A8 +008973 2 +008973 2 ; Sync X +008973 2 18 clc ; Transform to viewspace +008974 2 AD CB 92 lda WG_LOCALCURSORX +008977 2 79 D6 92 adc WG_VIEWRECORDS+0,y +00897A 2 +00897A 2 18 clc +00897B 2 79 DB 92 adc WG_VIEWRECORDS+5,y ; Transform to scrollspace +00897E 2 8D C9 92 sta WG_CURSORX +008981 2 +008981 2 ; Sync Y +008981 2 18 clc ; Transform to viewspace +008982 2 AD CC 92 lda WG_LOCALCURSORY +008985 2 79 D7 92 adc WG_VIEWRECORDS+1,y +008988 2 +008988 2 18 clc +008989 2 79 DC 92 adc WG_VIEWRECORDS+6,y ; Transform to scrollspace +00898C 2 8D CA 92 sta WG_CURSORY +00898F 2 +00898F 2 WGSyncGlobalCursor_done: +00898F 2 7A 68 RESTORE_AY +008991 2 60 rts +008992 2 +008992 2 +008992 2 +008992 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008992 2 ; WGScrollX +008992 2 ; Scrolls the current view horizontally +008992 2 ; A: New scroll amount +008992 2 ; Side effects: Clobbers A +008992 2 ; +008992 2 WGScrollX: +008992 2 5A phy +008993 2 48 pha +008994 2 +008994 2 AD CD 92 0A LDY_ACTIVEVIEW +008998 2 0A 0A 0A A8 +00899C 2 68 pla +00899D 2 99 DB 92 sta WG_VIEWRECORDS+5,y +0089A0 2 20 2B 8B jsr cacheClipPlanes ; Scroll offset changed, so clipping cache is stale +0089A3 2 +0089A3 2 WGScrollX_done: +0089A3 2 7A ply +0089A4 2 60 rts +0089A5 2 +0089A5 2 +0089A5 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0089A5 2 ; WGScrollXBy +0089A5 2 ; Scrolls the current view horizontally by a delta +0089A5 2 ; A: Scroll delta +0089A5 2 ; Side effects: Clobbers A,S0 +0089A5 2 ; +0089A5 2 WGScrollXBy: +0089A5 2 DA 5A SAVE_XY +0089A7 2 AA tax +0089A8 2 +0089A8 2 AD CD 92 0A LDY_ACTIVEVIEW +0089AC 2 0A 0A 0A A8 +0089B0 2 +0089B0 2 8A txa +0089B1 2 10 1E bpl WGScrollXBy_contentRight +0089B3 2 +0089B3 2 B9 D8 92 lda WG_VIEWRECORDS+2,y ; Compute left limit +0089B6 2 38 sec +0089B7 2 F9 DD 92 sbc WG_VIEWRECORDS+7,y +0089BA 2 85 19 sta SCRATCH0 +0089BC 2 +0089BC 2 8A txa ; Compute new scroll value +0089BD 2 18 clc +0089BE 2 79 DB 92 adc WG_VIEWRECORDS+5,y +0089C1 2 C5 19 cmp SCRATCH0 ; Clamp if needed +0089C3 2 30 05 bmi WGScrollXBy_clampLeft +0089C5 2 99 DB 92 sta WG_VIEWRECORDS+5,y +0089C8 2 80 19 bra WGScrollXBy_done +0089CA 2 +0089CA 2 WGScrollXBy_clampLeft: +0089CA 2 A5 19 lda SCRATCH0 +0089CC 2 99 DB 92 sta WG_VIEWRECORDS+5,y +0089CF 2 80 12 bra WGScrollXBy_done +0089D1 2 +0089D1 2 WGScrollXBy_contentRight: +0089D1 2 18 clc ; Compute new scroll value +0089D2 2 79 DB 92 adc WG_VIEWRECORDS+5,y +0089D5 2 F0 02 beq @0 ; Clamp if needed +0089D7 2 10 05 bpl WGScrollXBy_clampRight +0089D9 2 99 DB 92 @0: sta WG_VIEWRECORDS+5,y +0089DC 2 80 05 bra WGScrollXBy_done +0089DE 2 +0089DE 2 WGScrollXBy_clampRight: +0089DE 2 A9 00 lda #0 +0089E0 2 99 DB 92 sta WG_VIEWRECORDS+5,y +0089E3 2 +0089E3 2 WGScrollXBy_done: +0089E3 2 7A FA RESTORE_XY +0089E5 2 60 rts +0089E6 2 +0089E6 2 +0089E6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0089E6 2 ; WGScrollY +0089E6 2 ; Scrolls the current view vertically +0089E6 2 ; A: New scroll amount +0089E6 2 ; Side effects: Clobbers A +0089E6 2 ; +0089E6 2 WGScrollY: +0089E6 2 5A phy +0089E7 2 48 pha +0089E8 2 +0089E8 2 AD CD 92 0A LDY_ACTIVEVIEW +0089EC 2 0A 0A 0A A8 +0089F0 2 68 pla +0089F1 2 99 DC 92 sta WG_VIEWRECORDS+6,y +0089F4 2 20 2B 8B jsr cacheClipPlanes ; Scroll offset changed, so clipping cache is stale +0089F7 2 +0089F7 2 WGScrollY_done: +0089F7 2 7A ply +0089F8 2 60 rts +0089F9 2 +0089F9 2 +0089F9 2 +0089F9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0089F9 2 ; WGScrollYBy +0089F9 2 ; Scrolls the current view horizontally by a delta +0089F9 2 ; A: Scroll delta +0089F9 2 ; Side effects: Clobbers A,S0 +0089F9 2 ; +0089F9 2 WGScrollYBy: +0089F9 2 DA 5A SAVE_XY +0089FB 2 AA tax +0089FC 2 +0089FC 2 AD CD 92 0A LDY_ACTIVEVIEW +008A00 2 0A 0A 0A A8 +008A04 2 +008A04 2 8A txa +008A05 2 10 1E bpl WGScrollYBy_contentDown +008A07 2 +008A07 2 B9 D9 92 lda WG_VIEWRECORDS+3,y ; Compute bottom limit +008A0A 2 38 sec +008A0B 2 F9 DE 92 sbc WG_VIEWRECORDS+8,y +008A0E 2 85 19 sta SCRATCH0 +008A10 2 +008A10 2 8A txa ; Compute new scroll value +008A11 2 18 clc +008A12 2 79 DC 92 adc WG_VIEWRECORDS+6,y +008A15 2 C5 19 cmp SCRATCH0 ; Clamp if needed +008A17 2 30 05 bmi WGScrollYBy_clampTop +008A19 2 99 DC 92 sta WG_VIEWRECORDS+6,y +008A1C 2 80 19 bra WGScrollYBy_done +008A1E 2 +008A1E 2 WGScrollYBy_clampTop: +008A1E 2 A5 19 lda SCRATCH0 +008A20 2 99 DC 92 sta WG_VIEWRECORDS+6,y +008A23 2 80 12 bra WGScrollYBy_done +008A25 2 +008A25 2 WGScrollYBy_contentDown: +008A25 2 18 clc ; Compute new scroll value +008A26 2 79 DC 92 adc WG_VIEWRECORDS+6,y +008A29 2 F0 02 beq @0 ; Clamp if needed +008A2B 2 10 05 bpl WGScrollYBy_clampBottom +008A2D 2 99 DC 92 @0: sta WG_VIEWRECORDS+6,y +008A30 2 80 05 bra WGScrollYBy_done +008A32 2 +008A32 2 WGScrollYBy_clampBottom: +008A32 2 A9 00 lda #0 +008A34 2 99 DC 92 sta WG_VIEWRECORDS+6,y +008A37 2 +008A37 2 WGScrollYBy_done: +008A37 2 7A FA RESTORE_XY +008A39 2 60 rts +008A3A 2 +008A3A 2 +008A3A 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008A3A 2 ; WGViewPaintAll +008A3A 2 ; Repaints all views +008A3A 2 ; Side effects: Changes selected view +008A3A 2 ; +008A3A 2 WGViewPaintAll: +008A3A 2 48 DA 5A SAVE_AXY +008A3D 2 +008A3D 2 A2 00 ldx #0 +008A3F 2 +008A3F 2 WGViewPaintAll_loop: +008A3F 2 8A txa +008A40 2 20 57 87 jsr WGSelectView +008A43 2 +008A43 2 AD CD 92 0A LDY_ACTIVEVIEW +008A47 2 0A 0A 0A A8 +008A4B 2 B9 D8 92 lda WG_VIEWRECORDS+2,y ; Last view? +008A4E 2 F0 09 beq WGViewPaintAll_done +008A50 2 +008A50 2 20 16 87 jsr WGEraseViewContents +008A53 2 20 B6 85 jsr WGPaintView +008A56 2 E8 inx +008A57 2 80 E6 bra WGViewPaintAll_loop +008A59 2 +008A59 2 WGViewPaintAll_done: +008A59 2 7A FA 68 RESTORE_AXY +008A5C 2 60 rts +008A5D 2 +008A5D 2 +008A5D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008A5D 2 ; WGViewFromPoint +008A5D 2 ; Finds a view containing the given point +008A5D 2 ; PARAM0:X +008A5D 2 ; PARAM1:Y +008A5D 2 ; OUT A: View ID (or high bit set if no match) +008A5D 2 ; For Fancy Views, Upper nibble returned indicates feature hit: +008A5D 2 ; 0000 : Content region +008A5D 2 ; 0001 : Scroll arrow up +008A5D 2 ; 0010 : Scroll arrow down +008A5D 2 ; 0011 : Scroll arrow left +008A5D 2 ; 0100 : Scroll arrow right +008A5D 2 WGViewFromPoint: +008A5D 2 DA 5A SAVE_XY +008A5F 2 A5 19 48 A5 SAVE_ZPS +008A63 2 1A 48 +008A65 2 +008A65 2 A2 0F ldx #$f ; Scan views backwards, because controls are usually at the end +008A67 2 +008A67 2 WGViewFromPoint_loop: +008A67 2 8A txa +008A68 2 0A 0A 0A 0A LDY_AVIEW +008A6C 2 A8 +008A6D 2 +008A6D 2 B9 D8 92 lda WG_VIEWRECORDS+2,y +008A70 2 F0 67 beq WGViewFromPoint_loopNext ; Not an allocated view +008A72 2 +008A72 2 B9 DA 92 lda WG_VIEWRECORDS+4,y ; Fancy views are handled differently +008A75 2 29 0F and #$f +008A77 2 C9 01 cmp #VIEW_STYLE_FANCY +008A79 2 F0 0C beq WGViewFromPoint_loopFancy +008A7B 2 +008A7B 2 B9 D8 92 lda WG_VIEWRECORDS+2,y +008A7E 2 85 19 sta SCRATCH0 +008A80 2 B9 D9 92 lda WG_VIEWRECORDS+3,y +008A83 2 85 1A sta SCRATCH1 +008A85 2 80 0C bra WGViewFromPoint_loopCheckBounds +008A87 2 +008A87 2 WGViewFromPoint_loopFancy: +008A87 2 B9 D8 92 lda WG_VIEWRECORDS+2,y ; Include scrollbars +008A8A 2 1A inc +008A8B 2 85 19 sta SCRATCH0 +008A8D 2 B9 D9 92 lda WG_VIEWRECORDS+3,y +008A90 2 1A inc +008A91 2 85 1A sta SCRATCH1 +008A93 2 +008A93 2 WGViewFromPoint_loopCheckBounds: +008A93 2 A5 06 lda PARAM0 ; Check left edge +008A95 2 D9 D6 92 cmp WG_VIEWRECORDS+0,y +008A98 2 90 3F bcc WGViewFromPoint_loopNext +008A9A 2 +008A9A 2 A5 07 lda PARAM1 ; Check top edge +008A9C 2 D9 D7 92 cmp WG_VIEWRECORDS+1,y +008A9F 2 90 38 bcc WGViewFromPoint_loopNext +008AA1 2 +008AA1 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Check right edge +008AA4 2 18 clc +008AA5 2 65 19 adc SCRATCH0 +008AA7 2 C5 06 cmp PARAM0 +008AA9 2 90 2E bcc WGViewFromPoint_loopNext +008AAB 2 F0 2C beq WGViewFromPoint_loopNext +008AAD 2 +008AAD 2 B9 D7 92 lda WG_VIEWRECORDS+1,y ; Check bottom edge +008AB0 2 18 clc +008AB1 2 65 1A adc SCRATCH1 +008AB3 2 C5 07 cmp PARAM1 +008AB5 2 90 22 bcc WGViewFromPoint_loopNext +008AB7 2 F0 20 beq WGViewFromPoint_loopNext +008AB9 2 +008AB9 2 ; Found a match (in X) +008AB9 2 B9 DA 92 lda WG_VIEWRECORDS+4,y +008ABC 2 29 0F and #$f ; Mask off flag bits +008ABE 2 C9 01 cmp #VIEW_STYLE_FANCY +008AC0 2 D0 54 bne WGViewFromPoint_matchDone +008AC2 2 +008AC2 2 ; For fancy views, check scrollbars as well +008AC2 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Right scroll bar? +008AC5 2 18 clc +008AC6 2 65 19 adc SCRATCH0 +008AC8 2 3A dec +008AC9 2 C5 06 cmp PARAM0 +008ACB 2 D0 22 bne WGViewFromPoint_checkBottomScroll +008ACD 2 +008ACD 2 A5 07 lda PARAM1 ; Up arrow? +008ACF 2 D9 D7 92 cmp WG_VIEWRECORDS+1,y +008AD2 2 D0 0A bne WGViewFromPoint_checkDownArrow +008AD4 2 8A txa +008AD5 2 09 10 ora #WG_FEATURE_UP +008AD7 2 80 3C bra WGViewFromPoint_matchFancyDone +008AD9 2 +008AD9 2 WGViewFromPoint_loopNext: ; Inserted here for branch range +008AD9 2 CA dex +008ADA 2 30 44 bmi WGViewFromPoint_noMatch +008ADC 2 80 89 bra WGViewFromPoint_loop +008ADE 2 +008ADE 2 WGViewFromPoint_checkDownArrow: +008ADE 2 B9 D7 92 lda WG_VIEWRECORDS+1,y ; Down arrow? +008AE1 2 18 clc +008AE2 2 65 1A adc SCRATCH1 +008AE4 2 3A dec +008AE5 2 3A dec +008AE6 2 C5 07 cmp PARAM1 +008AE8 2 D0 2C bne WGViewFromPoint_matchDone +008AEA 2 8A txa +008AEB 2 09 20 ora #WG_FEATURE_DN +008AED 2 80 26 bra WGViewFromPoint_matchFancyDone +008AEF 2 +008AEF 2 WGViewFromPoint_checkBottomScroll: +008AEF 2 B9 D7 92 lda WG_VIEWRECORDS+1,y ; Bottom scroll bar? +008AF2 2 18 clc +008AF3 2 65 1A adc SCRATCH1 +008AF5 2 3A dec +008AF6 2 C5 07 cmp PARAM1 +008AF8 2 D0 1C bne WGViewFromPoint_matchDone +008AFA 2 A5 06 lda PARAM0 ; Left arrow? +008AFC 2 D9 D6 92 cmp WG_VIEWRECORDS+0,y +008AFF 2 D0 05 bne WGViewFromPoint_checkRightArrow +008B01 2 8A txa +008B02 2 09 30 ora #WG_FEATURE_LF +008B04 2 80 0F bra WGViewFromPoint_matchFancyDone +008B06 2 +008B06 2 WGViewFromPoint_checkRightArrow: +008B06 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Right arrow? +008B09 2 18 clc +008B0A 2 65 19 adc SCRATCH0 +008B0C 2 3A dec +008B0D 2 3A dec +008B0E 2 C5 06 cmp PARAM0 +008B10 2 D0 04 bne WGViewFromPoint_matchDone +008B12 2 8A txa +008B13 2 09 40 ora #WG_FEATURE_RT +008B15 2 +008B15 2 WGViewFromPoint_matchFancyDone: +008B15 2 AA tax +008B16 2 +008B16 2 WGViewFromPoint_matchDone: +008B16 2 68 85 1A 68 RESTORE_ZPS +008B1A 2 85 19 +008B1C 2 8A txa +008B1D 2 7A FA RESTORE_XY +008B1F 2 60 rts +008B20 2 +008B20 2 WGViewFromPoint_noMatch: +008B20 2 68 85 1A 68 RESTORE_ZPS +008B24 2 85 19 +008B26 2 A9 FF lda #$ff +008B28 2 7A FA RESTORE_XY +008B2A 2 60 rts +008B2B 2 +008B2B 2 +008B2B 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008B2B 2 ; cacheClipPlanes +008B2B 2 ; Internal routine to cache the clipping planes for the view +008B2B 2 ; +008B2B 2 cacheClipPlanes: +008B2B 2 48 5A SAVE_AY +008B2D 2 +008B2D 2 ; Compute clip planes in view space +008B2D 2 AD CD 92 0A LDY_ACTIVEVIEW +008B31 2 0A 0A 0A A8 +008B35 2 +008B35 2 B9 DB 92 lda WG_VIEWRECORDS+5,y ; Left edge +008B38 2 49 FF eor #$ff +008B3A 2 1A inc +008B3B 2 8D D1 92 sta WG_VIEWCLIP+0 +008B3E 2 +008B3E 2 18 clc +008B3F 2 79 D8 92 adc WG_VIEWRECORDS+2,y ; Right edge +008B42 2 8D D3 92 sta WG_VIEWCLIP+2 +008B45 2 +008B45 2 B9 DD 92 lda WG_VIEWRECORDS+7,y ; Right span (distance from window edge to view edge, in viewspace +008B48 2 38 sec +008B49 2 ED D3 92 sbc WG_VIEWCLIP+2 +008B4C 2 8D D5 92 sta WG_VIEWCLIP+4 +008B4F 2 +008B4F 2 B9 DC 92 lda WG_VIEWRECORDS+6,y ; Top edge +008B52 2 49 FF eor #$ff +008B54 2 1A inc +008B55 2 8D D2 92 sta WG_VIEWCLIP+1 +008B58 2 +008B58 2 18 clc +008B59 2 79 D9 92 adc WG_VIEWRECORDS+3,y ; Bottom edge +008B5C 2 8D D4 92 sta WG_VIEWCLIP+3 +008B5F 2 +008B5F 2 7A 68 RESTORE_AY +008B61 2 60 rts +008B62 2 +008B62 2 +008B62 2 +008B62 1 .include "mouse.s" +008B62 2 ; +008B62 2 ; mouse.s +008B62 2 ; Routines for handling the mouse +008B62 2 ; +008B62 2 ; Created by Quinn Dunki on 8/15/14. +008B62 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +008B62 2 ; +008B62 2 +008B62 2 +008B62 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008B62 2 ; ProDOS ROM entry points and constants +008B62 2 ; +008B62 2 PRODOS_MLI = $bf00 +008B62 2 +008B62 2 ALLOC_INTERRUPT = $40 +008B62 2 DEALLOC_INTERRUPT = $41 +008B62 2 +008B62 2 +008B62 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008B62 2 ; Mouse firmware ROM entry points and constants +008B62 2 ; +008B62 2 +008B62 2 ; These mouse firmware entry points are offsets from the firmware +008B62 2 ; entry point of the slot, and also indirect. +008B62 2 SETMOUSE = $12 +008B62 2 SERVEMOUSE = $13 +008B62 2 READMOUSE = $14 +008B62 2 CLEARMOUSE = $15 +008B62 2 POSMOUSE = $16 +008B62 2 CLAMPMOUSE = $17 +008B62 2 HOMEMOUSE = $18 +008B62 2 INITMOUSE = $19 +008B62 2 +008B62 2 MOUSTAT = $0778 ; + Slot Num +008B62 2 MOUSE_XL = $0478 ; + Slot Num +008B62 2 MOUSE_XH = $0578 ; + Slot Num +008B62 2 MOUSE_YL = $04f8 ; + Slot Num +008B62 2 MOUSE_YH = $05f8 ; + Slot Num +008B62 2 MOUSE_CLAMPL = $04f8 +008B62 2 MOUSE_CLAMPH = $05f8 +008B62 2 +008B62 2 MOUSTAT_MASK_BUTTONINT = %00000100 +008B62 2 MOUSTAT_MASK_MOVEINT = %00000010 +008B62 2 MOUSTAT_MASK_DOWN = %10000000 +008B62 2 MOUSTAT_MASK_WASDOWN = %01000000 +008B62 2 MOUSTAT_MASK_MOVED = %00100000 +008B62 2 +008B62 2 MOUSEMODE_OFF = $00 ; Mouse off +008B62 2 MOUSEMODE_PASSIVE = $01 ; Passive mode (polling only) +008B62 2 MOUSEMODE_MOVEINT = $03 ; Interrupts on movement +008B62 2 MOUSEMODE_BUTINT = $05 ; Interrupts on button +008B62 2 MOUSEMODE_COMBINT = $07 ; Interrupts on movement and button +008B62 2 +008B62 2 +008B62 2 ; Mouse firmware is all indirectly called, because +008B62 2 ; it moved around a lot in different Apple ][ ROM +008B62 2 ; versions. This macro helps abstracts this for us. +008B62 2 .macro CALLMOUSE name +008B62 2 ldx #name +008B62 2 jsr WGCallMouse +008B62 2 .endmacro +008B62 2 +008B62 2 +008B62 2 CH_MOUSEPOINTER = 'B' +008B62 2 +008B62 2 +008B62 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008B62 2 ; WGEnableMouse +008B62 2 ; Prepares the mouse for use +008B62 2 ; +008B62 2 WGEnableMouse: +008B62 2 48 pha +008B63 2 +008B63 2 8D 54 C0 SETSWITCH PAGE2OFF +008B66 2 +008B66 2 ; Find slot number and calculate the various indirections needed +008B66 2 20 FB 8B jsr WGFindMouse +008B69 2 B0 4E bcs WGEnableMouse_Error +008B6B 2 +008B6B 2 ; Install our interrupt handler via ProDOS (play nice!) +008B6B 2 20 00 BF jsr PRODOS_MLI +008B6E 2 40 .byte ALLOC_INTERRUPT +008B6F 2 C0 8D .addr WG_PRODOS_ALLOC +008B71 2 D0 46 bne WGEnableMouse_Error ; ProDOS will return here with Z clear on error +008B73 2 +008B73 2 ; Initialize the mouse +008B73 2 9C B8 8D stz WG_MOUSEPOS_X +008B76 2 9C B9 8D stz WG_MOUSEPOS_Y +008B79 2 9C BB 8D stz WG_MOUSEBG +008B7C 2 +008B7C 2 A2 19 20 E2 CALLMOUSE INITMOUSE +008B80 2 8B +008B81 2 B0 36 bcs WGEnableMouse_Error ; Firmware sets carry if mouse is not available +008B83 2 +008B83 2 A2 15 20 E2 CALLMOUSE CLEARMOUSE +008B87 2 8B +008B88 2 +008B88 2 A9 07 lda #MOUSEMODE_COMBINT ; Enable combination interrupt mode +008B8A 2 A2 12 20 E2 CALLMOUSE SETMOUSE +008B8E 2 8B +008B8F 2 +008B8F 2 ; Scale the mouse's range into something easy to do math with, +008B8F 2 ; while retaining as much range of motion and precision as possible +008B8F 2 A9 80 lda #$80 ; 640 horizontally +008B91 2 8D F8 04 sta MOUSE_CLAMPL +008B94 2 A9 02 lda #$02 +008B96 2 8D F8 05 sta MOUSE_CLAMPH +008B99 2 A9 00 lda #0 +008B9B 2 A2 17 20 E2 CALLMOUSE CLAMPMOUSE +008B9F 2 8B +008BA0 2 +008BA0 2 A9 E0 lda #$e0 ; 736 vertically +008BA2 2 8D F8 04 sta MOUSE_CLAMPL +008BA5 2 A9 02 lda #$02 +008BA7 2 8D F8 05 sta MOUSE_CLAMPH +008BAA 2 A9 01 lda #1 +008BAC 2 A2 17 20 E2 CALLMOUSE CLAMPMOUSE +008BB0 2 8B +008BB1 2 +008BB1 2 A9 01 lda #1 +008BB3 2 8D B7 8D sta WG_MOUSEACTIVE +008BB6 2 +008BB6 2 58 cli ; Once all setup is done, it's safe to enable interrupts +008BB7 2 80 03 bra WGEnableMouse_done +008BB9 2 +008BB9 2 WGEnableMouse_Error: +008BB9 2 9C B7 8D stz WG_MOUSEACTIVE +008BBC 2 +008BBC 2 WGEnableMouse_done: +008BBC 2 68 pla +008BBD 2 60 rts +008BBE 2 +008BBE 2 +008BBE 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008BBE 2 ; WGDisableMouse +008BBE 2 ; Shuts off the mouse when we're done with it +008BBE 2 ; +008BBE 2 WGDisableMouse: +008BBE 2 48 pha +008BBF 2 +008BBF 2 8D 54 C0 SETSWITCH PAGE2OFF +008BC2 2 +008BC2 2 AD B7 8D lda WG_MOUSEACTIVE ; Never activated the mouse +008BC5 2 F0 19 beq WGDisableMouse_done +008BC7 2 +008BC7 2 A5 00 lda MOUSEMODE_OFF +008BC9 2 A2 12 20 E2 CALLMOUSE SETMOUSE +008BCD 2 8B +008BCE 2 +008BCE 2 9C B7 8D stz WG_MOUSEACTIVE +008BD1 2 +008BD1 2 ; Remove our interrupt handler via ProDOS (done playing nice!) +008BD1 2 AD C1 8D lda WG_PRODOS_ALLOC+1 ; Copy interrupt ID that ProDOS gave us +008BD4 2 8D C5 8D sta WG_PRODOS_DEALLOC+1 +008BD7 2 +008BD7 2 20 00 BF jsr PRODOS_MLI +008BDA 2 41 .byte DEALLOC_INTERRUPT +008BDB 2 C4 8D .addr WG_PRODOS_DEALLOC +008BDD 2 +008BDD 2 20 04 8D jsr WGUndrawPointer ; Be nice if we're disabled during a program +008BE0 2 +008BE0 2 WGDisableMouse_done: +008BE0 2 68 pla +008BE1 2 60 rts +008BE2 2 +008BE2 2 +008BE2 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008BE2 2 ; WGCallMouse +008BE2 2 ; Calls a mouse firmware routine. Here's where we handle all +008BE2 2 ; the layers of indirection needed to call mouse firmware. The +008BE2 2 ; firmware moved in ROM several times over the life of the +008BE2 2 ; Apple ][, so it's kind of a hassle to call it. +008BE2 2 ; X: Name of routine (firmware offset constant) +008BE2 2 ; Side effects: Clobbers all registers +008BE2 2 WGCallMouse: +008BE2 2 8E E6 8B stx WGCallMouse+4 ; Use self-modifying code to smooth out some indirection +008BE5 2 +008BE5 2 ; This load address is overwritten by the above code, AND by the mouse set +008BE5 2 ; up code, to make sure we have the right slot entry point and firmware +008BE5 2 ; offset +008BE5 2 AE 00 C4 ldx $c400 ; Self-modifying code! +008BE8 2 8E BC 8D stx WG_MOUSE_JUMPL ; Get low byte of final jump from firmware +008BEB 2 +008BEB 2 08 php ; Note that mouse firmware is not re-entrant, +008BEC 2 78 sei ; so we must disable interrupts inside them +008BED 2 +008BED 2 20 F2 8B jsr WGCallMouse_redirect +008BF0 2 28 plp ; Restore interrupts to previous state +008BF1 2 60 rts +008BF2 2 +008BF2 2 WGCallMouse_redirect: +008BF2 2 AE BD 8D ldx WG_MOUSE_JUMPH +008BF5 2 AC BF 8D ldy WG_MOUSE_SLOTSHIFTED +008BF8 2 6C BC 8D jmp (WG_MOUSE_JUMPL) +008BFB 2 +008BFB 2 +008BFB 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008BFB 2 ; WGFindMouse +008BFB 2 ; Figures out which slot (//e) or port (//c) the mouse is in. +008BFB 2 ; It moved around a lot over the years. Sets it to 0 if no mouse +008BFB 2 ; could be found +008BFB 2 ; OUT C: Set if no mouse could be found +008BFB 2 WGFindMouse: +008BFB 2 48 DA SAVE_AX +008BFD 2 +008BFD 2 A2 07 ldx #7 +008BFF 2 +008BFF 2 WGFindMouse_loop: +008BFF 2 8A txa ; Compute slot firmware locations for this loop +008C00 2 09 C0 ora #$c0 +008C02 2 8D 13 8C sta WGFindMouse_loopModify+2 ; Self-modifying code! +008C05 2 8D 1A 8C sta WGFindMouse_loopModify+9 +008C08 2 8D 21 8C sta WGFindMouse_loopModify+16 +008C0B 2 8D 28 8C sta WGFindMouse_loopModify+23 +008C0E 2 8D 2F 8C sta WGFindMouse_loopModify+30 +008C11 2 +008C11 2 WGFindMouse_loopModify: +008C11 2 ; Check for the magic 5-byte pattern that gives away the mouse card +008C11 2 AD 05 C0 lda $c005 ; These addresses are modified in place on +008C14 2 C9 38 cmp #$38 ; each loop iteration +008C16 2 D0 1E bne WGFindMouse_nextSlot +008C18 2 AD 07 C0 lda $c007 +008C1B 2 C9 18 cmp #$18 +008C1D 2 D0 17 bne WGFindMouse_nextSlot +008C1F 2 AD 0B C0 lda $c00b +008C22 2 C9 01 cmp #$01 +008C24 2 D0 10 bne WGFindMouse_nextSlot +008C26 2 AD 0C C0 lda $c00c +008C29 2 C9 20 cmp #$20 +008C2B 2 D0 09 bne WGFindMouse_nextSlot +008C2D 2 AD FB C0 lda $c0fb +008C30 2 C9 D6 cmp #$d6 +008C32 2 D0 02 bne WGFindMouse_nextSlot +008C34 2 80 05 bra WGFindMouse_found +008C36 2 +008C36 2 WGFindMouse_nextSlot: +008C36 2 CA dex +008C37 2 30 1B bmi WGFindMouse_none +008C39 2 80 C4 bra WGFindMouse_loop +008C3B 2 +008C3B 2 WGFindMouse_found: +008C3B 2 ; Found it! Now configure all our indirection lookups +008C3B 2 8E BE 8D stx WG_MOUSE_SLOT +008C3E 2 A9 C0 lda #$c0 +008C40 2 0D BE 8D ora WG_MOUSE_SLOT +008C43 2 8D BD 8D sta WG_MOUSE_JUMPH +008C46 2 8D E7 8B sta WGCallMouse+5 ; Self-modifying code! +008C49 2 8A txa +008C4A 2 0A asl +008C4B 2 0A asl +008C4C 2 0A asl +008C4D 2 0A asl +008C4E 2 8D BF 8D sta WG_MOUSE_SLOTSHIFTED +008C51 2 18 clc +008C52 2 80 04 bra WGFindMouse_done +008C54 2 +008C54 2 WGFindMouse_none: +008C54 2 9C BE 8D stz WG_MOUSE_SLOT +008C57 2 38 sec +008C58 2 +008C58 2 WGFindMouse_done: +008C58 2 FA 68 RESTORE_AX +008C5A 2 60 rts +008C5B 2 +008C5B 2 +008C5B 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008C5B 2 ; WGMouseInterruptHandler +008C5B 2 ; Handles interrupts that may be related to the mouse +008C5B 2 ; This is a ProDOS-compliant interrupt handling routine, and +008C5B 2 ; should be installed and removed via ProDOS as needed. +008C5B 2 ; +008C5B 2 ; IMPORTANT: This routine is NOT MLI-reentrant, which means MLI +008C5B 2 ; calls can NOT be made within this handler. See page 108 of the +008C5B 2 ; ProDOS 8 Technical Reference Manual if this feature needs to be +008C5B 2 ; added. +008C5B 2 ; +008C5B 2 WGMouseInterruptHandler: +008C5B 2 D8 cld ; ProDOS interrupt handlers must open with this +008C5C 2 48 DA 5A SAVE_AXY +008C5F 2 +008C5F 2 A2 13 20 E2 CALLMOUSE SERVEMOUSE +008C63 2 8B +008C64 2 B0 64 bcs WGMouseInterruptHandler_disregard +008C66 2 +008C66 2 78 sei +008C67 2 +008C67 2 AD 1C C0 lda PAGE2 ; Need to preserve text bank, because we may interrupt rendering +008C6A 2 48 pha +008C6B 2 8D 54 C0 SETSWITCH PAGE2OFF +008C6E 2 +008C6E 2 AE BE 8D ldx WG_MOUSE_SLOT +008C71 2 BD 78 07 lda MOUSTAT,x ; Check interrupt status bits first, because READMOUSE clears them +008C74 2 29 04 and #MOUSTAT_MASK_BUTTONINT +008C76 2 D0 56 bne WGMouseInterruptHandler_button +008C78 2 +008C78 2 20 04 8D jsr WGUndrawPointer ; Erase the old mouse pointer +008C7B 2 +008C7B 2 ; Read the mouse state. Note that interrupts need to remain +008C7B 2 ; off until after the data is copied. +008C7B 2 A2 14 20 E2 CALLMOUSE READMOUSE +008C7F 2 8B +008C80 2 +008C80 2 AE BE 8D ldx WG_MOUSE_SLOT +008C83 2 BD 78 07 lda MOUSTAT,x ; Movement/button status bits are now valid +008C86 2 8D BA 8D sta WG_MOUSE_STAT +008C89 2 +008C89 2 ; Read mouse position and transform it into screen space +008C89 2 5E 78 05 lsr MOUSE_XH,x +008C8C 2 7E 78 04 ror MOUSE_XL,x +008C8F 2 5E 78 05 lsr MOUSE_XH,x +008C92 2 7E 78 04 ror MOUSE_XL,x +008C95 2 5E 78 05 lsr MOUSE_XH,x +008C98 2 7E 78 04 ror MOUSE_XL,x +008C9B 2 +008C9B 2 BD 78 04 lda MOUSE_XL,x +008C9E 2 8D B8 8D sta WG_MOUSEPOS_X +008CA1 2 +008CA1 2 5E F8 05 lsr MOUSE_YH,x +008CA4 2 7E F8 04 ror MOUSE_YL,x +008CA7 2 5E F8 05 lsr MOUSE_YH,x +008CAA 2 7E F8 04 ror MOUSE_YL,x +008CAD 2 5E F8 05 lsr MOUSE_YH,x +008CB0 2 7E F8 04 ror MOUSE_YL,x +008CB3 2 5E F8 05 lsr MOUSE_YH,x +008CB6 2 7E F8 04 ror MOUSE_YL,x +008CB9 2 5E F8 05 lsr MOUSE_YH,x +008CBC 2 7E F8 04 ror MOUSE_YL,x +008CBF 2 +008CBF 2 BD F8 04 lda MOUSE_YL,x +008CC2 2 8D B9 8D sta WG_MOUSEPOS_Y +008CC5 2 +008CC5 2 20 0C 8D jsr WGDrawPointer ; Redraw the pointer +008CC8 2 80 29 bra WGMouseInterruptHandler_intDone +008CCA 2 +008CCA 2 WGMouseInterruptHandler_disregard: +008CCA 2 ; Carry will still be set here, to notify ProDOS that +008CCA 2 ; this interrupt was not ours +008CCA 2 7A FA 68 RESTORE_AXY +008CCD 2 60 rts +008CCE 2 +008CCE 2 WGMouseInterruptHandler_button: +008CCE 2 A2 14 20 E2 CALLMOUSE READMOUSE +008CD2 2 8B +008CD3 2 AE BE 8D ldx WG_MOUSE_SLOT +008CD6 2 BD 78 07 lda MOUSTAT,x ; Movement/button status bits are now valid +008CD9 2 8D BA 8D sta WG_MOUSE_STAT +008CDC 2 +008CDC 2 2C BA 8D bit WG_MOUSE_STAT ; Check for rising edge of button state +008CDF 2 10 12 bpl WGMouseInterruptHandler_intDone +008CE1 2 +008CE1 2 AD B8 8D lda WG_MOUSEPOS_X ; Where did we click? +008CE4 2 85 06 sta PARAM0 +008CE6 2 AD B9 8D lda WG_MOUSEPOS_Y +008CE9 2 85 07 sta PARAM1 +008CEB 2 20 5D 8A jsr WGViewFromPoint +008CEE 2 30 03 bmi WGMouseInterruptHandler_intDone +008CF0 2 +008CF0 2 ; Button was clicked in a view, so make a note of it for later +008CF0 2 8D CF 92 sta WG_PENDINGACTIONVIEW +008CF3 2 +008CF3 2 WGMouseInterruptHandler_intDone: +008CF3 2 68 pla ; Restore text bank +008CF4 2 10 05 bpl WGMouseInterruptHandler_intDoneBankOff +008CF6 2 8D 55 C0 SETSWITCH PAGE2ON +008CF9 2 80 03 bra WGMouseInterruptHandler_done +008CFB 2 +008CFB 2 WGMouseInterruptHandler_intDoneBankOff: +008CFB 2 8D 54 C0 SETSWITCH PAGE2OFF +008CFE 2 +008CFE 2 WGMouseInterruptHandler_done: +008CFE 2 7A FA 68 RESTORE_AXY +008D01 2 +008D01 2 58 cli +008D02 2 18 clc ; Notify ProDOS this was our interrupt +008D03 2 60 rts +008D04 2 +008D04 2 +008D04 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008D04 2 ; WGUndrawPointer +008D04 2 ; Unplots the mouse pointer at current location +008D04 2 ; Side effects: Clobbers BASL,BASH +008D04 2 ; +008D04 2 WGUndrawPointer: +008D04 2 48 pha +008D05 2 A9 80 lda #$80 +008D07 2 20 1C 8D jsr renderPointer +008D0A 2 68 pla +008D0B 2 60 rts +008D0C 2 +008D0C 2 +008D0C 2 +008D0C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008D0C 2 ; WGDrawPointer +008D0C 2 ; Plots the mouse pointer at current location +008D0C 2 ; +008D0C 2 WGDrawPointer: +008D0C 2 48 pha +008D0D 2 A9 00 lda #0 +008D0F 2 20 1C 8D jsr renderPointer +008D12 2 68 pla +008D13 2 60 rts +008D14 2 +008D14 2 +008D14 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008D14 2 ; WGPointerDirty +008D14 2 ; Updates the background behind the mouse pointer without +008D14 2 ; modifying it's current render state. Assumes pointer is not +008D14 2 ; currently visible +008D14 2 ; +008D14 2 WGPointerDirty: +008D14 2 48 pha +008D15 2 A9 C0 lda #%11000000 +008D17 2 20 1C 8D jsr renderPointer +008D1A 2 68 pla +008D1B 2 60 rts +008D1C 2 +008D1C 2 +008D1C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008D1C 2 ; renderPointer +008D1C 2 ; Performs mouse-pointer-related rendering +008D1C 2 ; A: 0=draw, %10000000=undraw, %11000000=recapture background +008D1C 2 ; +008D1C 2 renderPointer: +008D1C 2 48 DA 5A SAVE_AXY +008D1F 2 8D B6 8D sta renderPointerMode +008D22 2 A5 28 lda BASL ; Need to preserve BAS, because we may interrupt rendering +008D24 2 48 pha +008D25 2 A5 29 lda BASH +008D27 2 48 pha +008D28 2 AD 1C C0 lda PAGE2 ; Need to preserve text bank, because we may interrupt rendering +008D2B 2 48 pha +008D2C 2 +008D2C 2 AD B7 8D lda WG_MOUSEACTIVE +008D2F 2 F0 70 beq renderPointer_done ; Mouse not enabled +008D31 2 +008D31 2 AE B9 8D ldx WG_MOUSEPOS_Y +008D34 2 E0 18 cpx #24 +008D36 2 B0 69 bcs renderPointer_done ; Mouse out of range (vertically) +008D38 2 +008D38 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of point +008D3B 2 85 28 sta BASL +008D3D 2 BD D7 94 lda TEXTLINES_H,x +008D40 2 85 29 sta BASH +008D42 2 +008D42 2 AD B8 8D lda WG_MOUSEPOS_X +008D45 2 C9 50 cmp #80 +008D47 2 B0 58 bcs renderPointer_done ; Mouse out of range (horizontally) +008D49 2 +008D49 2 4A lsr +008D4A 2 18 clc +008D4B 2 65 28 adc BASL +008D4D 2 85 28 sta BASL +008D4F 2 A9 00 lda #0 +008D51 2 65 29 adc BASH +008D53 2 85 29 sta BASH +008D55 2 +008D55 2 AD B8 8D lda WG_MOUSEPOS_X ; X even? +008D58 2 29 01 and #$01 +008D5A 2 D0 27 bne renderPointer_xOdd +008D5C 2 +008D5C 2 8D 55 C0 SETSWITCH PAGE2ON +008D5F 2 +008D5F 2 2C B6 8D bit renderPointerMode ; Draw or undraw? +008D62 2 10 02 bpl renderPointer_draw +008D64 2 50 14 bvc renderPointer_undraw +008D66 2 +008D66 2 renderPointer_draw: +008D66 2 B2 28 lda (BASL) ; Save background +008D68 2 C9 42 cmp #CH_MOUSEPOINTER ; Make sure we never capture ourselves and leave a "stamp" +008D6A 2 F0 03 beq renderPointer_drawSaved +008D6C 2 8D BB 8D sta WG_MOUSEBG +008D6F 2 +008D6F 2 renderPointer_drawSaved: +008D6F 2 2C B6 8D bit renderPointerMode ; Recapture or draw? +008D72 2 70 2D bvs renderPointer_done +008D74 2 +008D74 2 A9 42 lda #CH_MOUSEPOINTER ; Draw the pointer +008D76 2 92 28 sta (BASL) +008D78 2 80 27 bra renderPointer_done +008D7A 2 +008D7A 2 renderPointer_undraw: +008D7A 2 AD BB 8D lda WG_MOUSEBG +008D7D 2 F0 22 beq renderPointer_done ; No saved background yet +008D7F 2 92 28 sta (BASL) +008D81 2 80 1E bra renderPointer_done +008D83 2 +008D83 2 renderPointer_xOdd: +008D83 2 8D 54 C0 SETSWITCH PAGE2OFF +008D86 2 +008D86 2 2C B6 8D bit renderPointerMode ; Draw or undraw? +008D89 2 10 02 bpl renderPointer_drawOdd +008D8B 2 50 ED bvc renderPointer_undraw +008D8D 2 +008D8D 2 renderPointer_drawOdd: +008D8D 2 B2 28 lda (BASL) ; Save background +008D8F 2 C9 42 cmp #CH_MOUSEPOINTER ; Make sure we never capture ourselves and leave a "stamp" +008D91 2 F0 03 beq renderPointer_drawOddSaved +008D93 2 8D BB 8D sta WG_MOUSEBG +008D96 2 +008D96 2 renderPointer_drawOddSaved: +008D96 2 2C B6 8D bit renderPointerMode ; Recapture or draw? +008D99 2 70 06 bvs renderPointer_done +008D9B 2 +008D9B 2 A9 42 lda #CH_MOUSEPOINTER ; Draw the pointer +008D9D 2 92 28 sta (BASL) +008D9F 2 80 00 bra renderPointer_done +008DA1 2 +008DA1 2 renderPointer_done: +008DA1 2 68 pla ; Restore text bank +008DA2 2 10 05 bpl renderPointer_doneBankOff +008DA4 2 8D 55 C0 SETSWITCH PAGE2ON +008DA7 2 80 03 bra renderPointer_doneBAS +008DA9 2 +008DA9 2 renderPointer_doneBankOff: +008DA9 2 8D 54 C0 SETSWITCH PAGE2OFF +008DAC 2 +008DAC 2 renderPointer_doneBAS: +008DAC 2 68 pla ; Restore BAS +008DAD 2 85 29 sta BASH +008DAF 2 68 pla +008DB0 2 85 28 sta BASL +008DB2 2 +008DB2 2 7A FA 68 RESTORE_AXY +008DB5 2 60 rts +008DB6 2 +008DB6 2 renderPointerMode: +008DB6 2 00 .byte 0 +008DB7 2 +008DB7 2 +008DB7 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008DB7 2 ; Mouse API state +008DB7 2 ; +008DB7 2 WG_MOUSEACTIVE: +008DB7 2 00 .byte 0 +008DB8 2 +008DB8 2 WG_MOUSEPOS_X: +008DB8 2 27 .byte 39 +008DB9 2 WG_MOUSEPOS_Y: +008DB9 2 0B .byte 11 +008DBA 2 WG_MOUSE_STAT: +008DBA 2 00 .byte 0 +008DBB 2 WG_MOUSEBG: +008DBB 2 00 .byte 0 +008DBC 2 +008DBC 2 WG_MOUSE_JUMPL: +008DBC 2 00 .byte 0 +008DBD 2 WG_MOUSE_JUMPH: +008DBD 2 00 .byte 0 +008DBE 2 WG_MOUSE_SLOT: +008DBE 2 00 .byte 0 +008DBF 2 WG_MOUSE_SLOTSHIFTED: +008DBF 2 00 .byte 0 +008DC0 2 +008DC0 2 +008DC0 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008DC0 2 ; ProDOS system call parameter blocks +008DC0 2 ; +008DC0 2 WG_PRODOS_ALLOC: +008DC0 2 02 .byte 2 +008DC1 2 00 .byte 0 ; ProDOS returns an ID number for the interrupt here +008DC2 2 5B 8C .addr WGMouseInterruptHandler +008DC4 2 +008DC4 2 WG_PRODOS_DEALLOC: +008DC4 2 01 .byte 1 +008DC5 2 00 .byte 0 ; To be filled with ProDOS ID number +008DC6 2 +008DC6 2 +008DC6 2 +008DC6 1 .include "applesoft.s" +008DC6 2 ; +008DC6 2 ; applesoft.s +008DC6 2 ; Applesoft API via the & extension point +008DC6 2 ; +008DC6 2 ; Created by Quinn Dunki on 8/15/14. +008DC6 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +008DC6 2 ; +008DC6 2 +008DC6 2 +008DC6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008DC6 2 ; Applesoft ROM entry points and constants +008DC6 2 ; +008DC6 2 LINNUML = $0050 ; Scratch pad for calculating line numbers (LSB) +008DC6 2 LINNUMH = $0051 ; Scratch pad for calculating line numbers (MSB) +008DC6 2 CURLINL = $0075 ; Current line number (LSB) +008DC6 2 CURLINH = $0076 ; Current line number (MSB) +008DC6 2 CHRGET = $00b1 ; Advances text point and gets character in A +008DC6 2 CHRGOT = $00b7 ; Returns character at text pointer in A +008DC6 2 TXTPTRL = $00b8 ; Current location in BASIC listing (LSB) +008DC6 2 TXTPTRH = $00b9 ; Current location in BASIC listing (MSB) +008DC6 2 VARPNT = $0083 ; Return value for PTRGET +008DC6 2 +008DC6 2 FAC = $009d ; Floating point accumulator +008DC6 2 +008DC6 2 AMPVECTOR = $03f5 ; Ampersand entry vector +008DC6 2 ERROR = $d412 ; Reports error in X +008DC6 2 NEWSTT = $d7d2 ; Advance to next Applesoft statement +008DC6 2 GOTO = $d93e ; Entry point of Applesoft GOTO +008DC6 2 LINGET = $da0c ; Read a line number (16-bit integer) into LINNUM +008DC6 2 FRMNUM = $dd67 ; Evaluate an expression as a number and store in FAC +008DC6 2 CHKCOM = $debe ; Validates current character is a ',', then gets it +008DC6 2 SYNCHR = $dec0 ; Validates current character is what's in A +008DC6 2 AYINT = $e10c ; Convert FAC to 8-bit signed integer +008DC6 2 GETBYT = $e6f8 ; Gets an integer at text pointer, stores in X +008DC6 2 GETNUM = $e746 ; Gets an 8-bit, stores it X, skips past a comma +008DC6 2 PTRGET = $dfe3 ; Finds the Applesoft variable in memory at text pointer +008DC6 2 +008DC6 2 TOKEN_GOSUB = $b0 ; Applesoft's token for GOSUB +008DC6 2 TOKEN_HOME = $97 ; Applesoft's token for HOME +008DC6 2 TOKEN_PRINT = $ba ; Applesoft's token for PRINT +008DC6 2 TOKEN_MINUS = $c9 ; Applesoft's token for a minus sign +008DC6 2 TOKEN_DRAW = $94 ; Applesoft's token for DRAW +008DC6 2 TOKEN_PLOT = $8d ; Applesoft's token for PLOT +008DC6 2 TOKEN_GET = $be ; Applesoft's token for GET +008DC6 2 +008DC6 2 ERR_UNDEFINEDFUNC = 224 +008DC6 2 ERR_SYNTAX = 16 +008DC6 2 ERR_ENDOFDATA = 5 +008DC6 2 ERR_TOOLONG = 176 +008DC6 2 +008DC6 2 MAXCMDLEN = 6 +008DC6 2 +008DC6 2 +008DC6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008DC6 2 ; WGInitApplesoft +008DC6 2 ; Sets up Applesoft API +008DC6 2 ; +008DC6 2 WGInitApplesoft: +008DC6 2 48 pha +008DC7 2 +008DC7 2 A9 4C lda #$4c ; Patch in our jump vector for & +008DC9 2 8D F5 03 sta AMPVECTOR +008DCC 2 A9 D8 lda #WGAmpersand +008DD3 2 8D F7 03 sta AMPVECTOR+2 +008DD6 2 +008DD6 2 68 pla +008DD7 2 60 rts +008DD8 2 +008DD8 2 +008DD8 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008DD8 2 ; WGAmpersand +008DD8 2 ; The entry point from Applesoft. Applesoft text pointer +008DD8 2 ; will be positioned two after the '&', and accumulator will +008DD8 2 ; contain first character after the '&' +008DD8 2 ; Side effects: Clobbers All registers,S0 +008DD8 2 ; +008DD8 2 WGAmpersand: +008DD8 2 BA tsx ; Start by caching a valid stack state to return to Applesoft, +008DD9 2 8E FF 91 stx WG_STACKPTR ; in case we need to do so in a hurry +008DDC 2 +008DDC 2 85 19 sta SCRATCH0 +008DDE 2 +008DDE 2 A0 00 ldy #0 +008DE0 2 A6 19 ldx SCRATCH0 +008DE2 2 +008DE2 2 WGAmpersand_parseLoop: +008DE2 2 8A txa +008DE3 2 F0 17 beq WGAmpersand_matchStart ; Check for end-of-statement (CHRGET handles : and EOL) +008DE5 2 C9 28 cmp #'(' +008DE7 2 F0 13 beq WGAmpersand_matchStart +008DE9 2 +008DE9 2 99 DF 91 sta WGAmpersandCommandBuffer,y +008DEC 2 +008DEC 2 20 B1 00 jsr CHRGET +008DEF 2 AA tax +008DF0 2 +008DF0 2 C8 iny +008DF1 2 C0 07 cpy #MAXCMDLEN+1 +008DF3 2 D0 ED bne WGAmpersand_parseLoop +008DF5 2 +008DF5 2 WGAmpersand_parseFail: +008DF5 2 A2 E0 ldx #ERR_UNDEFINEDFUNC +008DF7 2 20 12 D4 jsr ERROR +008DFA 2 80 49 bra WGAmpersand_done +008DFC 2 +008DFC 2 WGAmpersand_matchStart: +008DFC 2 A9 00 lda #0 +008DFE 2 99 DF 91 sta WGAmpersandCommandBuffer,y ; Null terminate the buffer for matching +008E01 2 +008E01 2 A0 00 ldy #0 +008E03 2 A2 00 ldx #0 ; Command buffer now contains our API call +008E05 2 DA phx ; We stash the current command number on the stack +008E06 2 +008E06 2 WGAmpersand_matchLoop: +008E06 2 B9 DF 91 lda WGAmpersandCommandBuffer,y +008E09 2 F0 09 beq WGAmpersand_matchPossible +008E0B 2 DD 01 92 cmp WGAmpersandCommandTable,x +008E0E 2 D0 09 bne WGAmpersand_matchNext ; Not this one +008E10 2 +008E10 2 C8 iny +008E11 2 E8 inx +008E12 2 80 F2 bra WGAmpersand_matchLoop +008E14 2 +008E14 2 WGAmpersand_matchPossible: +008E14 2 BD 01 92 lda WGAmpersandCommandTable,x +008E17 2 F0 0F beq WGAmpersand_matchFound ; Got one! +008E19 2 +008E19 2 WGAmpersand_matchNext: +008E19 2 68 pla ; Advance index to next commmand in table +008E1A 2 1A inc +008E1B 2 48 pha +008E1C 2 0A asl +008E1D 2 0A asl +008E1E 2 0A asl +008E1F 2 AA tax +008E20 2 +008E20 2 E0 C8 cpx #WGAmpersandCommandTableEnd-WGAmpersandCommandTable +008E22 2 F0 1B beq WGAmpersand_matchFail ; Hit the end of the table +008E24 2 +008E24 2 A0 00 ldy #0 +008E26 2 80 DE bra WGAmpersand_matchLoop +008E28 2 +008E28 2 WGAmpersand_matchFound: +008E28 2 68 pla ; This is now the matching command number +008E29 2 1A inc +008E2A 2 0A asl +008E2B 2 0A asl +008E2C 2 0A asl +008E2D 2 A8 tay +008E2E 2 B9 FF 91 lda WGAmpersandCommandTable-2,y ; Prepare an indirect JSR to our command +008E31 2 8D 3B 8E sta WGAmpersand_commandJSR+1 ; Self-modifying code! +008E34 2 B9 00 92 lda WGAmpersandCommandTable-1,y +008E37 2 8D 3C 8E sta WGAmpersand_commandJSR+2 +008E3A 2 +008E3A 2 ; Self-modifying code! +008E3A 2 WGAmpersand_commandJSR: +008E3A 2 20 45 8E jsr WGAmpersand_done ; Address here overwritten with command +008E3D 2 80 06 bra WGAmpersand_done +008E3F 2 +008E3F 2 WGAmpersand_matchFail: +008E3F 2 68 pla ; We left command number on the stack while matching +008E40 2 A2 E0 ldx #ERR_UNDEFINEDFUNC +008E42 2 20 12 D4 jsr ERROR +008E45 2 +008E45 2 WGAmpersand_done: +008E45 2 60 rts +008E46 2 +008E46 2 +008E46 2 +008E46 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008E46 2 ; WGAmpersandBeginArguments +008E46 2 ; Begins reading an ampersand argument list +008E46 2 ; Side effects: Clobbers all registers +008E46 2 WGAmpersandBeginArguments: +008E46 2 48 pha +008E47 2 +008E47 2 A9 28 lda #'(' +008E49 2 20 C0 DE jsr SYNCHR ; Expect opening parenthesis +008E4C 2 +008E4C 2 68 pla +008E4D 2 60 rts +008E4E 2 +008E4E 2 +008E4E 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008E4E 2 ; WGAmpersandNextArgument +008E4E 2 ; Prepares for the next argument in the list +008E4E 2 ; Side effects: Clobbers all registers +008E4E 2 WGAmpersandNextArgument: +008E4E 2 20 B7 00 jsr CHRGOT +008E51 2 20 BE DE jsr CHKCOM ; Verify parameter separator +008E54 2 60 rts +008E55 2 +008E55 2 +008E55 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008E55 2 ; WGAmpersandEndArguments +008E55 2 ; Finishes reading an ampersand argument list +008E55 2 ; Side effects: Clobbers all registers +008E55 2 WGAmpersandEndArguments: +008E55 2 48 pha +008E56 2 +008E56 2 A9 29 lda #')' +008E58 2 20 C0 DE jsr SYNCHR ; Expect closing parenthesis +008E5B 2 +008E5B 2 68 pla +008E5C 2 60 rts +008E5D 2 +008E5D 2 +008E5D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008E5D 2 ; WGAmpersandIntArgument +008E5D 2 ; Reads an integer argument for the current command +008E5D 2 ; OUT A : The argument +008E5D 2 ; Side effects: Clobbers all registers +008E5D 2 WGAmpersandIntArgument: +008E5D 2 20 B7 00 jsr CHRGOT +008E60 2 C9 C9 cmp #TOKEN_MINUS +008E62 2 F0 05 beq WGAmpersandIntArgument_signed +008E64 2 +008E64 2 20 F8 E6 jsr GETBYT +008E67 2 8A txa +008E68 2 60 rts +008E69 2 +008E69 2 WGAmpersandIntArgument_signed: +008E69 2 20 B1 00 jsr CHRGET +008E6C 2 20 F8 E6 jsr GETBYT +008E6F 2 8A txa +008E70 2 49 FF eor #$ff +008E72 2 1A inc +008E73 2 60 rts +008E74 2 +008E74 2 +008E74 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008E74 2 ; WGAmpersandAddrArgument +008E74 2 ; Reads a 16-bit pointer (or integer) argument for the current command +008E74 2 ; OUT X : The argument (LSB) +008E74 2 ; OUT Y : The argument (MSB) +008E74 2 ; Side effects: Clobbers all registers +008E74 2 WGAmpersandAddrArgument: +008E74 2 20 B7 00 jsr CHRGOT +008E77 2 20 0C DA jsr LINGET +008E7A 2 +008E7A 2 A6 50 ldx LINNUML +008E7C 2 A4 51 ldy LINNUMH +008E7E 2 60 rts +008E7F 2 +008E7F 2 +008E7F 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008E7F 2 ; WGAmpersandStrArgument +008E7F 2 ; Reads a string argument for the current command in PARAM0/1. +008E7F 2 ; This string is copied into privately allocated memory. +008E7F 2 ; OUT X : Pointer to a stored copy of the string (LSB) +008E7F 2 ; OUT Y : Pointer to a stored copy of the string (MSB) +008E7F 2 ; Side effects: Clobbers P0/P1 and all registers +008E7F 2 WGAmpersandStrArgument: +008E7F 2 A9 22 lda #'"' +008E81 2 20 C0 DE jsr SYNCHR ; Expect opening quote +008E84 2 +008E84 2 A5 B8 lda TXTPTRL ; Allocate for, and copy the string at TXTPTR +008E86 2 85 06 sta PARAM0 +008E88 2 A5 B9 lda TXTPTRH +008E8A 2 85 07 sta PARAM1 +008E8C 2 A9 22 lda #'"' ; Specify quote as our terminator +008E8E 2 20 B9 7E jsr WGStoreStr +008E91 2 +008E91 2 WGAmpersandStrArgument_loop: +008E91 2 20 B1 00 jsr CHRGET ; Consume the string for Applesoft +008E94 2 F0 04 beq WGAmpersandStrArgument_done +008E96 2 C9 22 cmp #'"' ; Check for closing quote +008E98 2 D0 F7 bne WGAmpersandStrArgument_loop +008E9A 2 +008E9A 2 WGAmpersandStrArgument_done: +008E9A 2 A9 22 lda #'"' +008E9C 2 20 C0 DE jsr SYNCHR ; Expect closing quote +008E9F 2 +008E9F 2 A6 06 ldx PARAM0 +008EA1 2 A4 07 ldy PARAM1 +008EA3 2 60 rts +008EA4 2 +008EA4 2 +008EA4 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008EA4 2 ; WGAmpersandTempStrArgument +008EA4 2 ; Reads a string argument for the current command in PARAM0/1. +008EA4 2 ; This string is pointed to IN PLACE, and NOT copied. +008EA4 2 ; OUT X : Pointer to a stored copy of the string (LSB) +008EA4 2 ; OUT Y : Pointer to a stored copy of the string (MSB) +008EA4 2 ; OUT A : String length +008EA4 2 ; Side effects: Clobbers P0/P1 and all registers +008EA4 2 WGAmpersandTempStrArgument: +008EA4 2 A9 22 lda #'"' +008EA6 2 20 C0 DE jsr SYNCHR ; Expect opening quote +008EA9 2 +008EA9 2 A5 B8 lda TXTPTRL ; Grab current TXTPTR +008EAB 2 85 06 sta PARAM0 +008EAD 2 A5 B9 lda TXTPTRH +008EAF 2 85 07 sta PARAM1 +008EB1 2 +008EB1 2 WGAmpersandTempStrArgument_loop: +008EB1 2 20 B1 00 jsr CHRGET ; Consume the string for Applesoft +008EB4 2 F0 04 beq WGAmpersandTempStrArgument_done +008EB6 2 C9 22 cmp #'"' ; Check for closing quote +008EB8 2 D0 F7 bne WGAmpersandTempStrArgument_loop +008EBA 2 +008EBA 2 WGAmpersandTempStrArgument_done: +008EBA 2 A9 22 lda #'"' +008EBC 2 20 C0 DE jsr SYNCHR ; Expect closing quote +008EBF 2 +008EBF 2 ; Compute the 8-bit distance TXTPTR moved. Note that we can't simply +008EBF 2 ; count in the above loop, because CHRGET will skip ahead unpredictable +008EBF 2 ; amounts +008EBF 2 38 sec +008EC0 2 A5 B8 lda TXTPTRL +008EC2 2 E5 06 sbc PARAM0 +008EC4 2 3A dec +008EC5 2 +008EC5 2 A6 06 ldx PARAM0 ; Return results +008EC7 2 A4 07 ldy PARAM1 +008EC9 2 ; pla +008EC9 2 +008EC9 2 60 rts +008ECA 2 +008ECA 2 +008ECA 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008ECA 2 ; Ampersand API entry points +008ECA 2 ; +008ECA 2 +008ECA 2 +008ECA 2 +008ECA 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008ECA 2 ; WGAmpersand_HOME +008ECA 2 ; Clears the screen +008ECA 2 ; &HOME +008ECA 2 WGAmpersand_HOME: +008ECA 2 20 FF 7E jsr WGClearScreen +008ECD 2 20 9C 91 jsr WGBottomCursor +008ED0 2 +008ED0 2 60 rts +008ED1 2 +008ED1 2 +008ED1 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008ED1 2 ; WGAmpersand_DESK +008ED1 2 ; Render the desktop +008ED1 2 ; &DESK +008ED1 2 WGAmpersand_DESK: +008ED1 2 20 29 7F jsr WGDesktop +008ED4 2 20 9C 91 jsr WGBottomCursor +008ED7 2 60 rts +008ED8 2 +008ED8 2 +008ED8 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008ED8 2 ; WGAmpersand_WINDW +008ED8 2 ; Create a view +008ED8 2 ; &WINDW(id,style,x,y,width,height,canvas width,canvas height) +008ED8 2 WGAmpersand_WINDW: +008ED8 2 20 46 8E jsr WGAmpersandBeginArguments +008EDB 2 +008EDB 2 20 5D 8E jsr WGAmpersandIntArgument +008EDE 2 8D DF 91 sta WGAmpersandCommandBuffer+0 +008EE1 2 20 4E 8E jsr WGAmpersandNextArgument +008EE4 2 +008EE4 2 20 5D 8E jsr WGAmpersandIntArgument +008EE7 2 09 80 ora #VIEW_STYLE_APPLESOFT ; Flag this as an Applesoft-created view +008EE9 2 8D E0 91 sta WGAmpersandCommandBuffer+1 +008EEC 2 20 4E 8E jsr WGAmpersandNextArgument +008EEF 2 +008EEF 2 20 5D 8E jsr WGAmpersandIntArgument +008EF2 2 8D E1 91 sta WGAmpersandCommandBuffer+2 +008EF5 2 20 4E 8E jsr WGAmpersandNextArgument +008EF8 2 +008EF8 2 20 5D 8E jsr WGAmpersandIntArgument +008EFB 2 8D E2 91 sta WGAmpersandCommandBuffer+3 +008EFE 2 20 4E 8E jsr WGAmpersandNextArgument +008F01 2 +008F01 2 20 5D 8E jsr WGAmpersandIntArgument +008F04 2 8D E3 91 sta WGAmpersandCommandBuffer+4 +008F07 2 20 4E 8E jsr WGAmpersandNextArgument +008F0A 2 +008F0A 2 20 5D 8E jsr WGAmpersandIntArgument +008F0D 2 8D E4 91 sta WGAmpersandCommandBuffer+5 +008F10 2 20 4E 8E jsr WGAmpersandNextArgument +008F13 2 +008F13 2 20 5D 8E jsr WGAmpersandIntArgument +008F16 2 8D E5 91 sta WGAmpersandCommandBuffer+6 +008F19 2 20 4E 8E jsr WGAmpersandNextArgument +008F1C 2 +008F1C 2 20 5D 8E jsr WGAmpersandIntArgument +008F1F 2 8D E6 91 sta WGAmpersandCommandBuffer+7 +008F22 2 +008F22 2 20 55 8E jsr WGAmpersandEndArguments +008F25 2 +008F25 2 A9 DF 85 06 CALL16 WGCreateView,WGAmpersandCommandBuffer +008F29 2 A9 91 85 07 +008F2D 2 20 B9 84 +008F30 2 +008F30 2 20 16 87 jsr WGEraseViewContents +008F33 2 20 B6 85 jsr WGPaintView +008F36 2 20 9C 91 jsr WGBottomCursor +008F39 2 60 rts +008F3A 2 +008F3A 2 +008F3A 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008F3A 2 ; WGAmpersand_CHKBX +008F3A 2 ; Create a checkbox +008F3A 2 ; &CHKBX(id,x,y,"title") +008F3A 2 WGAmpersand_CHKBX: +008F3A 2 20 46 8E jsr WGAmpersandBeginArguments +008F3D 2 +008F3D 2 20 5D 8E jsr WGAmpersandIntArgument +008F40 2 8D DF 91 sta WGAmpersandCommandBuffer+0 +008F43 2 20 4E 8E jsr WGAmpersandNextArgument +008F46 2 +008F46 2 20 5D 8E jsr WGAmpersandIntArgument +008F49 2 8D E0 91 sta WGAmpersandCommandBuffer+1 +008F4C 2 20 4E 8E jsr WGAmpersandNextArgument +008F4F 2 +008F4F 2 20 5D 8E jsr WGAmpersandIntArgument +008F52 2 8D E1 91 sta WGAmpersandCommandBuffer+2 +008F55 2 20 4E 8E jsr WGAmpersandNextArgument +008F58 2 +008F58 2 20 7F 8E jsr WGAmpersandStrArgument +008F5B 2 8E E2 91 stx WGAmpersandCommandBuffer+3 +008F5E 2 8C E3 91 sty WGAmpersandCommandBuffer+4 +008F61 2 +008F61 2 20 55 8E jsr WGAmpersandEndArguments +008F64 2 +008F64 2 A9 DF 85 06 CALL16 WGCreateCheckbox,WGAmpersandCommandBuffer +008F68 2 A9 91 85 07 +008F6C 2 20 0F 85 +008F6F 2 +008F6F 2 AD CD 92 0A LDY_ACTIVEVIEW ; Flag this as an Applesoft-created view +008F73 2 0A 0A 0A A8 +008F77 2 A9 80 lda #VIEW_STYLE_APPLESOFT +008F79 2 19 DA 92 ora WG_VIEWRECORDS+4,y +008F7C 2 99 DA 92 sta WG_VIEWRECORDS+4,y +008F7F 2 +008F7F 2 20 B6 85 jsr WGPaintView +008F82 2 20 9C 91 jsr WGBottomCursor +008F85 2 +008F85 2 60 rts +008F86 2 +008F86 2 +008F86 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008F86 2 ; WGAmpersand_BUTTN +008F86 2 ; Create a button +008F86 2 ; &BUTTN(id,x,y,width,lineNum,"title") +008F86 2 WGAmpersand_BUTTN: +008F86 2 20 46 8E jsr WGAmpersandBeginArguments +008F89 2 +008F89 2 20 5D 8E jsr WGAmpersandIntArgument +008F8C 2 8D DF 91 sta WGAmpersandCommandBuffer+0 +008F8F 2 20 4E 8E jsr WGAmpersandNextArgument +008F92 2 +008F92 2 20 5D 8E jsr WGAmpersandIntArgument +008F95 2 8D E0 91 sta WGAmpersandCommandBuffer+1 +008F98 2 20 4E 8E jsr WGAmpersandNextArgument +008F9B 2 +008F9B 2 20 5D 8E jsr WGAmpersandIntArgument +008F9E 2 8D E1 91 sta WGAmpersandCommandBuffer+2 +008FA1 2 20 4E 8E jsr WGAmpersandNextArgument +008FA4 2 +008FA4 2 20 5D 8E jsr WGAmpersandIntArgument +008FA7 2 8D E2 91 sta WGAmpersandCommandBuffer+3 +008FAA 2 20 4E 8E jsr WGAmpersandNextArgument +008FAD 2 +008FAD 2 20 74 8E jsr WGAmpersandAddrArgument +008FB0 2 8E E3 91 stx WGAmpersandCommandBuffer+4 +008FB3 2 8C E4 91 sty WGAmpersandCommandBuffer+5 +008FB6 2 20 4E 8E jsr WGAmpersandNextArgument +008FB9 2 +008FB9 2 20 7F 8E jsr WGAmpersandStrArgument +008FBC 2 8E E5 91 stx WGAmpersandCommandBuffer+6 +008FBF 2 8C E6 91 sty WGAmpersandCommandBuffer+7 +008FC2 2 +008FC2 2 20 55 8E jsr WGAmpersandEndArguments +008FC5 2 +008FC5 2 A9 DF 85 06 CALL16 WGCreateButton,WGAmpersandCommandBuffer +008FC9 2 A9 91 85 07 +008FCD 2 20 5E 85 +008FD0 2 +008FD0 2 AD CD 92 0A LDY_ACTIVEVIEW ; Flag this as an Applesoft-created view +008FD4 2 0A 0A 0A A8 +008FD8 2 A9 80 lda #VIEW_STYLE_APPLESOFT +008FDA 2 19 DA 92 ora WG_VIEWRECORDS+4,y +008FDD 2 99 DA 92 sta WG_VIEWRECORDS+4,y +008FE0 2 +008FE0 2 20 B6 85 jsr WGPaintView +008FE3 2 20 9C 91 jsr WGBottomCursor +008FE6 2 +008FE6 2 60 rts +008FE7 2 +008FE7 2 +008FE7 2 +008FE7 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008FE7 2 ; WGAmpersand_SEL +008FE7 2 ; Select a view +008FE7 2 ; &SEL(id) +008FE7 2 WGAmpersand_SEL: +008FE7 2 20 46 8E jsr WGAmpersandBeginArguments +008FEA 2 20 5D 8E jsr WGAmpersandIntArgument +008FED 2 +008FED 2 20 57 87 jsr WGSelectView +008FF0 2 +008FF0 2 20 55 8E jsr WGAmpersandEndArguments +008FF3 2 60 rts +008FF4 2 +008FF4 2 +008FF4 2 +008FF4 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008FF4 2 ; WGAmpersand_FOC +008FF4 2 ; Focuses selected view +008FF4 2 ; &FOC +008FF4 2 WGAmpersand_FOC: +008FF4 2 20 64 87 jsr WGViewFocus +008FF7 2 20 9C 91 jsr WGBottomCursor +008FFA 2 60 rts +008FFB 2 +008FFB 2 +008FFB 2 +008FFB 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +008FFB 2 ; WGAmpersand_FOCN +008FFB 2 ; Focuses next view +008FFB 2 ; &FOCN +008FFB 2 WGAmpersand_FOCN: +008FFB 2 20 82 87 jsr WGViewFocusNext +008FFE 2 20 9C 91 jsr WGBottomCursor +009001 2 60 rts +009002 2 +009002 2 +009002 2 +009002 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009002 2 ; WGAmpersand_FOCP +009002 2 ; Focuses previous view +009002 2 ; &FOCP +009002 2 WGAmpersand_FOCP: +009002 2 20 B3 87 jsr WGViewFocusPrev +009005 2 20 9C 91 jsr WGBottomCursor +009008 2 60 rts +009009 2 +009009 2 +009009 2 +009009 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009009 2 ; WGAmpersand_ACT +009009 2 ; Takes action on focused view +009009 2 ; &ACT +009009 2 WGAmpersand_ACT: +009009 2 20 2D 88 jsr WGViewFocusAction +00900C 2 20 9C 91 jsr WGBottomCursor +00900F 2 +00900F 2 AD D0 92 lda WG_GOSUB +009012 2 D0 01 bne WGAmpersand_ACTGosub +009014 2 60 rts +009015 2 +009015 2 WGAmpersand_ACTGosub: +009015 2 4C B9 91 jmp WGGosub ; No coming back from an Applesoft GOSUB! +009018 2 +009018 2 +009018 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009018 2 ; WGAmpersand_STACT +009018 2 ; Sets the callback for the selected view +009018 2 ; &STACT(lineNum) +009018 2 WGAmpersand_STACT: +009018 2 20 46 8E jsr WGAmpersandBeginArguments +00901B 2 +00901B 2 20 74 8E jsr WGAmpersandAddrArgument +00901E 2 86 06 stx PARAM0 +009020 2 84 07 sty PARAM1 +009022 2 +009022 2 20 55 8E jsr WGAmpersandEndArguments +009025 2 +009025 2 20 38 89 jsr WGViewSetAction +009028 2 60 rts +009029 2 +009029 2 +009029 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009029 2 ; WGAmpersand_TITLE +009029 2 ; Sets the title for the selected view +009029 2 ; &TITLE("title") +009029 2 WGAmpersand_TITLE: +009029 2 20 46 8E jsr WGAmpersandBeginArguments +00902C 2 +00902C 2 20 7F 8E jsr WGAmpersandStrArgument +00902F 2 86 06 stx PARAM0 +009031 2 84 07 sty PARAM1 +009033 2 +009033 2 20 55 8E jsr WGAmpersandEndArguments +009036 2 +009036 2 20 21 89 jsr WGViewSetTitle +009039 2 20 B6 85 jsr WGPaintView +00903C 2 +00903C 2 60 rts +00903D 2 +00903D 2 +00903D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00903D 2 ; WGAmpersand_CURSR +00903D 2 ; Sets the cursor position in selected viewspace +00903D 2 ; &CURSR(x,y) +00903D 2 WGAmpersand_CURSR: +00903D 2 20 46 8E jsr WGAmpersandBeginArguments +009040 2 +009040 2 20 5D 8E jsr WGAmpersandIntArgument +009043 2 85 06 sta PARAM0 +009045 2 20 4E 8E jsr WGAmpersandNextArgument +009048 2 +009048 2 20 5D 8E jsr WGAmpersandIntArgument +00904B 2 85 07 sta PARAM1 +00904D 2 +00904D 2 20 55 8E jsr WGAmpersandEndArguments +009050 2 +009050 2 20 4F 89 jsr WGSetCursor +009053 2 +009053 2 60 rts +009054 2 +009054 2 +009054 2 +009054 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009054 2 ; WGAmpersand_PRINT +009054 2 ; Prints a string in the selected view at the local cursor +009054 2 ; &PRINT("string") +009054 2 WGAmpersand_PRINT: +009054 2 20 46 8E jsr WGAmpersandBeginArguments +009057 2 +009057 2 20 A4 8E jsr WGAmpersandTempStrArgument +00905A 2 86 06 stx PARAM0 +00905C 2 84 07 sty PARAM1 +00905E 2 48 pha +00905F 2 +00905F 2 20 55 8E jsr WGAmpersandEndArguments +009062 2 +009062 2 ; We're pointing to the string directly in the Applesoft +009062 2 ; source, so we need to NULL-terminate it for printing. In +009062 2 ; order to avoid copying the whole thing, we'll do something +009062 2 ; kinda dirty here. +009062 2 68 pla +009063 2 A8 tay +009064 2 B1 06 lda (PARAM0),y ; Cache the byte at the end of the string +009066 2 48 pha +009067 2 +009067 2 A9 00 lda #0 +009069 2 91 06 sta (PARAM0),y ; Null-terminate the string in-place +00906B 2 +00906B 2 20 90 7F jsr WGPrint +00906E 2 +00906E 2 68 pla +00906F 2 91 06 sta (PARAM0),y ; Put original byte back +009071 2 +009071 2 60 rts +009072 2 +009072 2 +009072 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009072 2 ; WGAmpersand_SCR +009072 2 ; Sets scroll position of selected view +009072 2 ; &SCR(x,y) +009072 2 WGAmpersand_SCR: +009072 2 20 46 8E jsr WGAmpersandBeginArguments +009075 2 +009075 2 20 5D 8E jsr WGAmpersandIntArgument +009078 2 48 pha +009079 2 20 4E 8E jsr WGAmpersandNextArgument +00907C 2 +00907C 2 20 5D 8E jsr WGAmpersandIntArgument +00907F 2 48 pha +009080 2 +009080 2 20 55 8E jsr WGAmpersandEndArguments +009083 2 +009083 2 68 pla +009084 2 20 E6 89 jsr WGScrollY +009087 2 68 pla +009088 2 20 92 89 jsr WGScrollX +00908B 2 +00908B 2 60 rts +00908C 2 +00908C 2 +00908C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00908C 2 ; WGAmpersand_SCRBY +00908C 2 ; Adjusts scroll position of selected view by a delta +00908C 2 ; &SCRBY(x,y) +00908C 2 WGAmpersand_SCRBY: +00908C 2 20 46 8E jsr WGAmpersandBeginArguments +00908F 2 +00908F 2 20 5D 8E jsr WGAmpersandIntArgument +009092 2 48 pha +009093 2 20 4E 8E jsr WGAmpersandNextArgument +009096 2 +009096 2 20 5D 8E jsr WGAmpersandIntArgument +009099 2 48 pha +00909A 2 +00909A 2 20 55 8E jsr WGAmpersandEndArguments +00909D 2 +00909D 2 68 pla +00909E 2 20 F9 89 jsr WGScrollYBy +0090A1 2 68 pla +0090A2 2 20 A5 89 jsr WGScrollXBy +0090A5 2 +0090A5 2 60 rts +0090A6 2 +0090A6 2 +0090A6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0090A6 2 ; WGAmpersand_GOSUB +0090A6 2 ; A custom gosub, because we can. Only for testing at the moment +0090A6 2 ; &GOSUB +0090A6 2 WGAmpersand_GOSUB: +0090A6 2 A9 E8 lda #$e8 +0090A8 2 85 06 sta PARAM0 +0090AA 2 A9 03 lda #$03 +0090AC 2 85 07 sta PARAM1 +0090AE 2 4C B9 91 jmp WGGosub +0090B1 2 +0090B1 2 +0090B1 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0090B1 2 ; WGAmpersand_ERASE +0090B1 2 ; Erases the contents of the selected view +0090B1 2 ; &ERASE +0090B1 2 WGAmpersand_ERASE: +0090B1 2 20 16 87 jsr WGEraseViewContents +0090B4 2 20 9C 91 jsr WGBottomCursor +0090B7 2 60 rts +0090B8 2 +0090B8 2 +0090B8 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0090B8 2 ; WGAmpersand_FILL +0090B8 2 ; Fills a rectangle with a character +0090B8 2 ; &FILL(x,y,width,height,char) +0090B8 2 WGAmpersand_FILL: +0090B8 2 20 46 8E jsr WGAmpersandBeginArguments +0090BB 2 +0090BB 2 20 5D 8E jsr WGAmpersandIntArgument +0090BE 2 85 06 sta PARAM0 +0090C0 2 20 4E 8E jsr WGAmpersandNextArgument +0090C3 2 +0090C3 2 20 5D 8E jsr WGAmpersandIntArgument +0090C6 2 85 07 sta PARAM1 +0090C8 2 20 4E 8E jsr WGAmpersandNextArgument +0090CB 2 +0090CB 2 20 5D 8E jsr WGAmpersandIntArgument +0090CE 2 85 08 sta PARAM2 +0090D0 2 20 4E 8E jsr WGAmpersandNextArgument +0090D3 2 +0090D3 2 20 5D 8E jsr WGAmpersandIntArgument +0090D6 2 85 09 sta PARAM3 +0090D8 2 20 4E 8E jsr WGAmpersandNextArgument +0090DB 2 +0090DB 2 20 5D 8E jsr WGAmpersandIntArgument +0090DE 2 09 80 ora #$80 ; Convert to Apple format +0090E0 2 48 pha +0090E1 2 +0090E1 2 20 55 8E jsr WGAmpersandEndArguments +0090E4 2 7A ply +0090E5 2 +0090E5 2 20 98 80 jsr WGFillRect +0090E8 2 20 9C 91 jsr WGBottomCursor +0090EB 2 +0090EB 2 60 rts +0090EC 2 +0090EC 2 +0090EC 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0090EC 2 ; WGAmpersand_DRAW +0090EC 2 ; Strokes a rectangle with a character +0090EC 2 ; &DRAW(x,y,width,height) +0090EC 2 WGAmpersand_DRAW: +0090EC 2 20 46 8E jsr WGAmpersandBeginArguments +0090EF 2 +0090EF 2 20 5D 8E jsr WGAmpersandIntArgument +0090F2 2 85 06 sta PARAM0 +0090F4 2 20 4E 8E jsr WGAmpersandNextArgument +0090F7 2 +0090F7 2 20 5D 8E jsr WGAmpersandIntArgument +0090FA 2 85 07 sta PARAM1 +0090FC 2 20 4E 8E jsr WGAmpersandNextArgument +0090FF 2 +0090FF 2 20 5D 8E jsr WGAmpersandIntArgument +009102 2 85 08 sta PARAM2 +009104 2 20 4E 8E jsr WGAmpersandNextArgument +009107 2 +009107 2 20 5D 8E jsr WGAmpersandIntArgument +00910A 2 85 09 sta PARAM3 +00910C 2 +00910C 2 20 55 8E jsr WGAmpersandEndArguments +00910F 2 +00910F 2 20 24 81 jsr WGStrokeRect +009112 2 20 9C 91 jsr WGBottomCursor +009115 2 +009115 2 60 rts +009116 2 +009116 2 +009116 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009116 2 ; WGAmpersand_PNT +009116 2 ; Repaints the selected view +009116 2 ; &PNT +009116 2 WGAmpersand_PNT: +009116 2 20 B6 85 jsr WGPaintView +009119 2 20 9C 91 jsr WGBottomCursor +00911C 2 60 rts +00911D 2 +00911D 2 +00911D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00911D 2 ; WGAmpersand_PNTA +00911D 2 ; Repaints all views +00911D 2 ; &PNTA +00911D 2 WGAmpersand_PNTA: +00911D 2 20 3A 8A jsr WGViewPaintAll +009120 2 20 9C 91 jsr WGBottomCursor +009123 2 60 rts +009124 2 +009124 2 +009124 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009124 2 ; WGAmpersand_PLOT +009124 2 ; Plots a single character (in Apple format) +009124 2 ; &PLOT(x,y,value) +009124 2 WGAmpersand_PLOT: +009124 2 20 46 8E jsr WGAmpersandBeginArguments +009127 2 +009127 2 20 5D 8E jsr WGAmpersandIntArgument +00912A 2 8D C9 92 sta WG_CURSORX +00912D 2 20 4E 8E jsr WGAmpersandNextArgument +009130 2 +009130 2 20 5D 8E jsr WGAmpersandIntArgument +009133 2 8D CA 92 sta WG_CURSORY +009136 2 20 4E 8E jsr WGAmpersandNextArgument +009139 2 +009139 2 20 5D 8E jsr WGAmpersandIntArgument +00913C 2 48 pha +00913D 2 +00913D 2 20 55 8E jsr WGAmpersandEndArguments +009140 2 +009140 2 68 pla +009141 2 20 55 7F jsr WGPlot +009144 2 20 9C 91 jsr WGBottomCursor +009147 2 +009147 2 60 rts +009148 2 +009148 2 +009148 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009148 2 ; WGAmpersand_MOUSE +009148 2 ; Enable or disable the mouse +009148 2 ; &MOUSE(enable) +009148 2 WGAmpersand_MOUSE: +009148 2 20 46 8E jsr WGAmpersandBeginArguments +00914B 2 20 5D 8E jsr WGAmpersandIntArgument +00914E 2 +00914E 2 48 pha +00914F 2 20 55 8E jsr WGAmpersandEndArguments +009152 2 +009152 2 68 pla +009153 2 F0 04 beq WGAmpersand_MOUSEoff +009155 2 20 62 8B jsr WGEnableMouse +009158 2 60 rts +009159 2 +009159 2 WGAmpersand_MOUSEoff: +009159 2 20 BE 8B jsr WGDisableMouse +00915C 2 60 rts +00915D 2 +00915D 2 +00915D 2 +00915D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00915D 2 ; WGAmpersand_PDACT +00915D 2 ; Performs any pending view action +00915D 2 ; &PDACT +00915D 2 WGAmpersand_PDACT: +00915D 2 AD CF 92 lda WG_PENDINGACTIONVIEW +009160 2 30 06 bmi WGAmpersand_PDACTdone +009162 2 +009162 2 20 97 88 jsr WGPendingViewAction +009165 2 20 9C 91 jsr WGBottomCursor +009168 2 +009168 2 WGAmpersand_PDACTdone: +009168 2 AD D0 92 lda WG_GOSUB +00916B 2 D0 01 bne WGAmpersand_PDACTGosub +00916D 2 60 rts +00916E 2 +00916E 2 WGAmpersand_PDACTGosub: +00916E 2 4C B9 91 jmp WGGosub ; No coming back from an Applesoft GOSUB! +009171 2 +009171 2 +009171 2 +009171 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +009171 2 ; WGAmpersand_GET +009171 2 ; A non-blocking version of Applesoft GET. Returns 0 if no key +009171 2 ; is pending +009171 2 ; &GET(A$) +009171 2 +009171 2 WGAmpersand_GET: +009171 2 20 46 8E jsr WGAmpersandBeginArguments +009174 2 +009174 2 20 E3 DF jsr PTRGET +009177 2 AD 00 C0 lda KBD +00917A 2 10 07 bpl WGAmpersand_GETnone ; No key pending +00917C 2 +00917C 2 8D 10 C0 sta KBDSTRB ; Clear strobe and high bit +00917F 2 29 7F and #%01111111 +009181 2 80 02 bra WGAmpersand_GETstore +009183 2 +009183 2 WGAmpersand_GETnone: +009183 2 A9 00 lda #0 +009185 2 +009185 2 WGAmpersand_GETstore: +009185 2 A0 00 ldy #0 +009187 2 +009187 2 8D 00 92 sta WG_KEYBUFFER ; Store the key +00918A 2 A9 01 lda #1 ; Create an Applesoft string record in the +00918C 2 91 83 sta (VARPNT),y ; variable's location +00918E 2 C8 iny +00918F 2 A9 00 lda #WG_KEYBUFFER +009196 2 91 83 sta (VARPNT),y +009198 2 +009198 2 20 55 8E jsr WGAmpersandEndArguments +00919B 2 60 rts +00919C 2 +00919C 2 +00919C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +00919C 2 ; WGBottomCursor +00919C 2 ; Leave the cursor state in a place that Applesoft is happy with +00919C 2 ; +00919C 2 WGBottomCursor: +00919C 2 48 5A SAVE_AY +00919E 2 +00919E 2 A9 00 lda #0 +0091A0 2 85 24 sta CH +0091A2 2 8D 7B 05 sta OURCH +0091A5 2 A9 17 lda #23 +0091A7 2 85 25 sta CV +0091A9 2 8D FB 05 sta OURCV +0091AC 2 +0091AC 2 AD EE 94 lda TEXTLINES_H+23 +0091AF 2 85 29 sta BASH +0091B1 2 AD 06 95 lda TEXTLINES_L+23 +0091B4 2 85 28 sta BASL +0091B6 2 +0091B6 2 7A 68 RESTORE_AY +0091B8 2 60 rts +0091B9 2 +0091B9 2 +0091B9 2 +0091B9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0091B9 2 ; WGGosub +0091B9 2 ; Performs an Applesoft GOSUB to a line number +0091B9 2 ; PARAM0: Line number (LSB) +0091B9 2 ; PARAM1: Line number (MSB) +0091B9 2 ; +0091B9 2 WGGosub: +0091B9 2 A9 00 lda #0 +0091BB 2 8D D0 92 sta WG_GOSUB ; Clear the flag +0091BE 2 +0091BE 2 ; Can't come back from what we're about to do, so cleanup from the +0091BE 2 ; original Ampersand entry point now! This is some seriously voodoo +0091BE 2 ; shit we're gonna pull here. +0091BE 2 AE FF 91 ldx WG_STACKPTR +0091C1 2 9A txs +0091C2 2 +0091C2 2 ; Fake an Applesoft GOSUB by pushing the same stuff it would do +0091C2 2 A5 B9 lda TXTPTRH +0091C4 2 48 pha +0091C5 2 A5 B8 lda TXTPTRL +0091C7 2 48 pha +0091C8 2 A5 76 lda CURLINH +0091CA 2 48 pha +0091CB 2 A5 75 lda CURLINL +0091CD 2 48 pha +0091CE 2 A9 B0 lda #TOKEN_GOSUB +0091D0 2 48 pha +0091D1 2 +0091D1 2 ; Here's the tricky bit- we jump into Applesoft's GOTO +0091D1 2 ; just after the part where it reads the line number. This +0091D1 2 ; allows us to piggy back on the hard work of finding the +0091D1 2 ; line number in the Applesoft source code, and storing +0091D1 2 ; it in the TXTPTR (thus performing the jump portion of +0091D1 2 ; a GOSUB). Since GOSUB normally falls through into GOTO, +0091D1 2 ; by faking the setup portion of the GOSUB, then leaving +0091D1 2 ; the state as GOTO expects it, we can fake the entire +0091D1 2 ; process to GOSUB to a line number we specify +0091D1 2 A5 06 lda PARAM0 +0091D3 2 85 50 sta LINNUML +0091D5 2 A5 07 lda PARAM1 +0091D7 2 85 51 sta LINNUMH +0091D9 2 +0091D9 2 20 41 D9 jsr GOTO+3 +0091DC 2 +0091DC 2 ; The goto has pointed the interpreter at the subroutine, +0091DC 2 ; so now advance to the next statement to continue executing. +0091DC 2 ; We'll never regain control, which is why we had to clean +0091DC 2 ; up from the ampersand entry before we got here. +0091DC 2 4C D2 D7 jmp NEWSTT +0091DF 2 +0091DF 2 +0091DF 2 +0091DF 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0091DF 2 ; Applesoft API state +0091DF 2 ; +0091DF 2 +0091DF 2 WGAmpersandCommandBuffer: +0091DF 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0091E3 2 00 00 00 00 +0091E7 2 00 00 00 00 +0091EF 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0091F3 2 00 00 00 00 +0091F7 2 00 00 00 00 +0091FE 2 WGAmpersandCommandBufferEnd: +0091FE 2 00 .byte 0 ; Make sure this last byte is always kept as a terminator +0091FF 2 +0091FF 2 WG_STACKPTR: ; A place to save the stack pointer for tricky Applesoft manipulation +0091FF 2 00 .byte 0 +009200 2 +009200 2 WG_KEYBUFFER: ; A phony string buffer for non-blocking GET +009200 2 00 .byte 0 +009201 2 +009201 2 +009201 2 ; Jump table for ampersand commands. +009201 2 ; Each row is 8 bytes (5 for name, NULL terminator, 2 for address) +009201 2 ; +009201 2 ; Note the strange constants in place of some strings- this is because +009201 2 ; all text is tokenized before we receive it, so reserved words may +009201 2 ; be compressed +009201 2 ; +009201 2 WGAmpersandCommandTable: +009201 2 +009201 2 97 00 00 00 .byte TOKEN_HOME,0,0,0,0,0 +009205 2 00 00 +009207 2 CA 8E .addr WGAmpersand_HOME +009209 2 +009209 2 44 45 53 4B .byte "DESK",0,0 +00920D 2 00 00 +00920F 2 D1 8E .addr WGAmpersand_DESK +009211 2 +009211 2 57 49 4E 44 .byte "WINDW",0 +009215 2 57 00 +009217 2 D8 8E .addr WGAmpersand_WINDW +009219 2 +009219 2 43 48 4B 42 .byte "CHKBX",0 +00921D 2 58 00 +00921F 2 3A 8F .addr WGAmpersand_CHKBX +009221 2 +009221 2 42 55 54 54 .byte "BUTTN",0 +009225 2 4E 00 +009227 2 86 8F .addr WGAmpersand_BUTTN +009229 2 +009229 2 53 45 4C 00 .byte "SEL",0,0,0 +00922D 2 00 00 +00922F 2 E7 8F .addr WGAmpersand_SEL +009231 2 +009231 2 46 4F 43 00 .byte "FOC",0,0,0 +009235 2 00 00 +009237 2 F4 8F .addr WGAmpersand_FOC +009239 2 +009239 2 46 4F 43 4E .byte "FOCN",0,0 +00923D 2 00 00 +00923F 2 FB 8F .addr WGAmpersand_FOCN +009241 2 +009241 2 46 4F 43 50 .byte "FOCP",0,0 +009245 2 00 00 +009247 2 02 90 .addr WGAmpersand_FOCP +009249 2 +009249 2 41 43 54 00 .byte "ACT",0,0,0 +00924D 2 00 00 +00924F 2 09 90 .addr WGAmpersand_ACT +009251 2 +009251 2 53 54 41 43 .byte "STACT",0 +009255 2 54 00 +009257 2 18 90 .addr WGAmpersand_STACT +009259 2 +009259 2 54 49 54 4C .byte "TITLE",0 +00925D 2 45 00 +00925F 2 29 90 .addr WGAmpersand_TITLE +009261 2 +009261 2 43 55 52 53 .byte "CURSR",0 +009265 2 52 00 +009267 2 3D 90 .addr WGAmpersand_CURSR +009269 2 +009269 2 53 43 52 00 .byte "SCR",0,0,0 +00926D 2 00 00 +00926F 2 72 90 .addr WGAmpersand_SCR +009271 2 +009271 2 53 43 52 42 .byte "SCRBY",0 +009275 2 59 00 +009277 2 8C 90 .addr WGAmpersand_SCRBY +009279 2 +009279 2 45 52 41 53 .byte "ERASE",0 +00927D 2 45 00 +00927F 2 B1 90 .addr WGAmpersand_ERASE +009281 2 +009281 2 BA 00 00 00 .byte TOKEN_PRINT,0,0,0,0,0 +009285 2 00 00 +009287 2 54 90 .addr WGAmpersand_PRINT +009289 2 +009289 2 46 49 4C 4C .byte "FILL",0,0 +00928D 2 00 00 +00928F 2 B8 90 .addr WGAmpersand_FILL +009291 2 +009291 2 94 00 00 00 .byte TOKEN_DRAW,0,0,0,0,0 +009295 2 00 00 +009297 2 EC 90 .addr WGAmpersand_DRAW +009299 2 +009299 2 50 4E 54 00 .byte "PNT",0,0,0 +00929D 2 00 00 +00929F 2 16 91 .addr WGAmpersand_PNT +0092A1 2 +0092A1 2 50 4E 54 41 .byte "PNTA",0,0 +0092A5 2 00 00 +0092A7 2 1D 91 .addr WGAmpersand_PNTA +0092A9 2 +0092A9 2 8D 00 00 00 .byte TOKEN_PLOT,0,0,0,0,0 +0092AD 2 00 00 +0092AF 2 24 91 .addr WGAmpersand_PLOT +0092B1 2 +0092B1 2 4D 4F 55 53 .byte "MOUSE",0 +0092B5 2 45 00 +0092B7 2 48 91 .addr WGAmpersand_MOUSE +0092B9 2 +0092B9 2 50 44 41 43 .byte "PDACT",0 +0092BD 2 54 00 +0092BF 2 5D 91 .addr WGAmpersand_PDACT +0092C1 2 +0092C1 2 BE 00 00 00 .byte TOKEN_GET,0,0,0,0,0 +0092C5 2 00 00 +0092C7 2 71 91 .addr WGAmpersand_GET +0092C9 2 +0092C9 2 ;.byte TOKEN_GOSUB,0,0,0,0,0,0,0,0,0,0,0,0,0 ; For internal testing of the procedural gosub +0092C9 2 ;.addr WGAmpersand_GOSUB +0092C9 2 +0092C9 2 +0092C9 2 WGAmpersandCommandTableEnd: +0092C9 2 +0092C9 2 +0092C9 1 .include "memory.s" +0092C9 2 ; +0092C9 2 ; memory.s +0092C9 2 ; Memory mapping information +0092C9 2 ; +0092C9 2 ; Created by Quinn Dunki on 8/15/14. +0092C9 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +0092C9 2 ; +0092C9 2 +0092C9 2 +0092C9 2 ; Constants +0092C9 2 +0092C9 2 CHAR_NORMAL = $ff +0092C9 2 CHAR_INVERSE = $3f +0092C9 2 CHAR_FLASH = $7f +0092C9 2 +0092C9 2 VIEW_STYLE_PLAIN = $00 +0092C9 2 VIEW_STYLE_FANCY = $01 +0092C9 2 VIEW_STYLE_CHECK = $02 +0092C9 2 VIEW_STYLE_BUTTON = $03 +0092C9 2 +0092C9 2 VIEW_STYLE_TAKESFOCUS = $02 ; Styles >= this one are selectable +0092C9 2 +0092C9 2 VIEW_STYLE_APPLESOFT = $80 ; High nybble flag bit for views created from Applesoft +0092C9 2 +0092C9 2 IRQVECTORL = $03fe +0092C9 2 IRQVECTORH = $03ff +0092C9 2 +0092C9 2 MEMBITMAP = $bf58 ; ProDOS 8 system memory allocation bitmap +0092C9 2 +0092C9 2 ; ROM entry points +0092C9 2 +0092C9 2 COUT = $fded +0092C9 2 BASCALC = $fbc1 +0092C9 2 PRBYTE = $fdda +0092C9 2 RDKEY = $fd0c +0092C9 2 BELL = $fbdd +0092C9 2 +0092C9 2 +0092C9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0092C9 2 ; System state +0092C9 2 ; +0092C9 2 WG_CURSORX: ; In screenspace +0092C9 2 00 .byte 0 +0092CA 2 WG_CURSORY: +0092CA 2 00 .byte 0 +0092CB 2 +0092CB 2 WG_LOCALCURSORX: ; In current viewspace +0092CB 2 00 .byte 0 +0092CC 2 WG_LOCALCURSORY: +0092CC 2 00 .byte 0 +0092CD 2 +0092CD 2 WG_ACTIVEVIEW: +0092CD 2 00 .byte 0 +0092CE 2 +0092CE 2 WG_FOCUSVIEW: +0092CE 2 00 .byte 0 +0092CF 2 +0092CF 2 WG_PENDINGACTIONVIEW: +0092CF 2 00 .byte 0 +0092D0 2 +0092D0 2 WG_GOSUB: ; Set if an Applesoft gosub was generated by a view action +0092D0 2 00 .byte 0 +0092D1 2 +0092D1 2 WG_VIEWCLIP: +0092D1 2 ; X0,Y0,X1,Y1. Edges of current window, in view space, right span +0092D1 2 00 00 00 00 .byte 0,0,0,0,0 +0092D5 2 00 +0092D6 2 +0092D6 2 WG_VIEWRECORDS: +0092D6 2 ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 +0092D6 2 ; X, Y, Screen Width, Screen Height, Style, X Offset, Y Offset, View Width, View Height, State, CallbackL, CallbackH, TitleL, TitleH +0092D6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0092DA 2 00 00 00 00 +0092DE 2 00 00 00 00 +0092E6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0092EA 2 00 00 00 00 +0092EE 2 00 00 00 00 +0092F6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0092FA 2 00 00 00 00 +0092FE 2 00 00 00 00 +009306 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00930A 2 00 00 00 00 +00930E 2 00 00 00 00 +009316 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00931A 2 00 00 00 00 +00931E 2 00 00 00 00 +009326 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00932A 2 00 00 00 00 +00932E 2 00 00 00 00 +009336 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00933A 2 00 00 00 00 +00933E 2 00 00 00 00 +009346 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00934A 2 00 00 00 00 +00934E 2 00 00 00 00 +009356 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00935A 2 00 00 00 00 +00935E 2 00 00 00 00 +009366 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00936A 2 00 00 00 00 +00936E 2 00 00 00 00 +009376 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00937A 2 00 00 00 00 +00937E 2 00 00 00 00 +009386 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00938A 2 00 00 00 00 +00938E 2 00 00 00 00 +009396 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00939A 2 00 00 00 00 +00939E 2 00 00 00 00 +0093A6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0093AA 2 00 00 00 00 +0093AE 2 00 00 00 00 +0093B6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0093BA 2 00 00 00 00 +0093BE 2 00 00 00 00 +0093C6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0093CA 2 00 00 00 00 +0093CE 2 00 00 00 00 +0093D6 2 +0093D6 2 WG_STRINGS: ; Fixed-size block allocator for strings (view titles, mainly) +0093D6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0093DA 2 00 00 00 00 +0093DE 2 00 00 00 00 +0093E6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0093EA 2 00 00 00 00 +0093EE 2 00 00 00 00 +0093F6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0093FA 2 00 00 00 00 +0093FE 2 00 00 00 00 +009406 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00940A 2 00 00 00 00 +00940E 2 00 00 00 00 +009416 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00941A 2 00 00 00 00 +00941E 2 00 00 00 00 +009426 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00942A 2 00 00 00 00 +00942E 2 00 00 00 00 +009436 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00943A 2 00 00 00 00 +00943E 2 00 00 00 00 +009446 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00944A 2 00 00 00 00 +00944E 2 00 00 00 00 +009456 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00945A 2 00 00 00 00 +00945E 2 00 00 00 00 +009466 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00946A 2 00 00 00 00 +00946E 2 00 00 00 00 +009476 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00947A 2 00 00 00 00 +00947E 2 00 00 00 00 +009486 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00948A 2 00 00 00 00 +00948E 2 00 00 00 00 +009496 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +00949A 2 00 00 00 00 +00949E 2 00 00 00 00 +0094A6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0094AA 2 00 00 00 00 +0094AE 2 00 00 00 00 +0094B6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0094BA 2 00 00 00 00 +0094BE 2 00 00 00 00 +0094C6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0094CA 2 00 00 00 00 +0094CE 2 00 00 00 00 +0094D6 2 +0094D6 2 WG_SCRATCHA: +0094D6 2 00 .byte 0 +0094D7 2 +0094D7 2 +0094D7 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +0094D7 2 ; Lookup tables +0094D7 2 ; +0094D7 2 +0094D7 2 ; Video memory +0094D7 2 TEXTLINES_H: +0094D7 2 04 .byte $04 ;0 +0094D8 2 04 .byte $04 ;1 +0094D9 2 05 .byte $05 ;2 +0094DA 2 05 .byte $05 ;3 +0094DB 2 06 .byte $06 ;4 +0094DC 2 06 .byte $06 ;5 +0094DD 2 07 .byte $07 ;6 +0094DE 2 07 .byte $07 ;7 +0094DF 2 04 .byte $04 ;8 +0094E0 2 04 .byte $04 ;9 +0094E1 2 05 .byte $05 ;10 +0094E2 2 05 .byte $05 ;11 +0094E3 2 06 .byte $06 ;12 +0094E4 2 06 .byte $06 ;13 +0094E5 2 07 .byte $07 ;14 +0094E6 2 07 .byte $07 ;15 +0094E7 2 04 .byte $04 ;16 +0094E8 2 04 .byte $04 ;17 +0094E9 2 05 .byte $05 ;18 +0094EA 2 05 .byte $05 ;19 +0094EB 2 06 .byte $06 ;20 +0094EC 2 06 .byte $06 ;21 +0094ED 2 07 .byte $07 ;22 +0094EE 2 07 .byte $07 ;23 +0094EF 2 +0094EF 2 TEXTLINES_L: +0094EF 2 00 .byte $00 ;0 +0094F0 2 80 .byte $80 ;1 +0094F1 2 00 .byte $00 ;2 +0094F2 2 80 .byte $80 ;3 +0094F3 2 00 .byte $00 ;4 +0094F4 2 80 .byte $80 ;5 +0094F5 2 00 .byte $00 ;6 +0094F6 2 80 .byte $80 ;7 +0094F7 2 28 .byte $28 ;8 +0094F8 2 A8 .byte $a8 ;9 +0094F9 2 28 .byte $28 ;10 +0094FA 2 A8 .byte $a8 ;11 +0094FB 2 28 .byte $28 ;12 +0094FC 2 A8 .byte $a8 ;13 +0094FD 2 28 .byte $28 ;14 +0094FE 2 A8 .byte $a8 ;15 +0094FF 2 50 .byte $50 ;16 +009500 2 D0 .byte $d0 ;17 +009501 2 50 .byte $50 ;18 +009502 2 D0 .byte $d0 ;19 +009503 2 50 .byte $50 ;20 +009504 2 D0 .byte $d0 ;21 +009505 2 50 .byte $50 ;22 +009506 2 D0 .byte $d0 ;23 +009507 2 +009507 2 +009507 1 +009507 1 +009507 1 +009507 1 ; Suppress some linker warnings - Must be the last thing in the file +009507 1 .SEGMENT "ZPSAVE" +009507 1 .SEGMENT "EXEHDR" +009507 1 .SEGMENT "STARTUP" +009507 1 .SEGMENT "INIT" +009507 1 .SEGMENT "LOWCODE" +009507 1 +009507 1 diff --git a/gui.s b/weegui.s similarity index 77% rename from gui.s rename to weegui.s index 5714132..4e13f96 100644 --- a/gui.s +++ b/weegui.s @@ -7,7 +7,7 @@ ; -.org $4000 +.org $7e00 ; Common definitions @@ -24,7 +24,7 @@ main: ; This is the non-negotiable entry point used by applications Don't move it! -; $4004 +; $7e04 @@ -79,8 +79,34 @@ WGEntryPointTable: WGInit: SAVE_AXY - jsr WG80 - jsr WGInitApplesoft + ; Reserve our memory in the ProDOS allocator bitmap + ; + ; See section 5.1.4 in the ProDOS 8 Technical Reference Manual + ; for an explanation of these values. We're reserving memory + ; pages $7e-$95 so that ProDOS won't use our memory for file + ; buffers, or allow Applesoft to step on us + ; + ; Byte in System Bitmap : Bit within byte + ; 0f:001 + ; 0f:000 + ; 10:111 .. 10:000 + ; 11:111 .. 11:000 + ; 12:111 + ; 12:110 + ; 12:101 + ; 12:100 + ; 12:011 + ; 12:010 + lda #%00000011 + tsb MEMBITMAP + $0f + lda #$ff + tsb MEMBITMAP + $10 + tsb MEMBITMAP + $11 + lda #%11111100 + tsb MEMBITMAP + $12 + + jsr WG80 ; Enter 80-col text mode + jsr WGInitApplesoft ; Set up Applesoft API ldy #15 ; Clear our block allocators WGInit_clearMemLoop: