TweetFollow Us on Twitter

VBL with Mach1
Volume Number:2
Issue Number:6
Column Tag:Threaded Code

Install a VBL Task with Mach1

By Jörg Langowski, EMBL, c/o I.L.L., Grenoble, Cedex, France, Editorial Board

Installing a Forth VBL Task - another CRT saver

Bob Denny's Article on vertical blanking tasks (MT V1#9) has been a constant challenge to me ever since it appeared. It seemed that there are certain things that one just could not do in Forth - the installation of an independently running task in the system heap being one of them. After all, where do you put the Forth runtime support when you leave Forth and want the task to run?

Another thing that would be difficult to do in Forth, for example, would be a desk accessory. In general, any tasks that will run independently and concurrently in the Mac operating system are almost impossible to handle with a language that needs a runtime interpreter to work.

After Mach1 came in, one could sort of see the light at the end of the tunnel. Here was a Forth that created real 68000 machine language output, and in principle its code could run anywhere without ever needing any runtime package. Maybe this makes some of the 'impossible' things that I mentioned less impossible.

Still, Mach1 does contain runtime support. Multitasking is the most important one, but by no means all, even the LOOP of a DO...LOOP structure is compiled as a JSR to a kernel routine.

The first rule for creating programs that are not only 'stand-alone applications', but self-contained code, is to avoid all references to kernel routines from within the program. This general statement will hold for any Forth system; given a Forth assembler, enough patience and a good set of macro definitions one will always be able to write code that is self-contained and won't need the runtime interpreter (e.g. using inline macros similar to the ones defined in MT V1#9, Forth column). Mach1 code doesn't contain too many references to its kernel anyway, so it should be much easier to accomplish what we try to do.

Our problem is to create a piece of code that does exactly what Bob Denny's CRT saver does: intercepts the GetNextEvent trap and updates a counter to keep track of when the last non-null event happened, and a VBL task that looks at that counter and blanks the screen whenever a certain time has elapsed after the last non-null event. Furthermore, the GetNextEvent intercept routine will repaint the screen after it has been blanked when a new non-null event occurs.

For the purpose of illustration, Listing 1 shows some Mach1 code that installs a very similar screen blanker as a background task under Mach1. This is the simple way to do it and will of course run only within the Mach1 system.

Short explanation of the program: the blankout routine opens a new GrafPort and paints its portRect (default size: whole screen) with the default pattern (black).

This routine is installed into one background task, CRTsaver, that checks continuously whether the time after the last 'relevant' event is larger than a preset value and blanks the screen if it is; thereafter, it unblanks the screen when a new event is received. The task's infinite loop contains a PAUSE to give control back to the scheduler.

The second background task, eventmonitor, checks for events by calling EventAvail. Whenever a 'relevant' event occurs, it is intercepted by this routine and the event tracking counter last.action updated.

Try and install these routines on your Mach1 system, and you'll have a fine CRT saver. Note that the multitasking system is not running while the screen is dark; I did this to keep it completely blank. You can insert a PAUSE in the event waiting loop of do.blank; in that case, all tasks will keep running, but you'll have a small white rectangle on the black screen (the cursor which is still active).

Installing the CRT saver as an independent VBL task

The example in Listing 1 contains many things that will just not work independently of the Mach1 runtime package:

- background tasks;

- variable definitions, which are kept separate from the main code block;

- JSR references to the kernel are not contained here, but could be easily in other tasks (as mentioned, a simple DO...LOOP);

- there are certain trap calls that are incompatible with the VBL task mechanism; as mentioned in IM, trap routines that move, purge or reallocate memory may not be called from a VBL task, the reason being that if the task happens to interrupt the memory manager and then calls the memory manager itself, very strange effects may result.

The list of 'forbidden' routines (IM, Addison-Wesley Vol. III in the appendix) is impressive, and EventAvail is one of them. The Quickdraw calls in blankout are also forbidden.

-The Mach1 data stack is maintained through the A6 register. In self-contained code, this register will have to be set up to point to a local stack area when the code is first entered. Also, for safety reasons the complete register file should be saved on entering and restored on exit.

An impressive list of restrictions; however, the example in Listing 2 shows that it is not that bad after all.

First, we may not use variables anymore. Any variable storage space should be defined within our piece of code. This can be done using create or header. References to variables thus defined must be through ['] (in colon definitions) or ' (in direct execution). If a create variable is referenced by name in a colon definition, a JSR to its code is compiled. create's own code again references the kernel and therefore cannot be used for self-contained programs.

If you use variables in this way, you can't call them directly by name after storing something there, because the create execution code will be overwritten. You'll always have to 'tick' their addresses on the stack.

Second, the screen blanker has to be rewritten; we store the black pattern into the screen area directly instead of calling Quickdraw routines, which may not be used. This is a little slower (Quickdraw really deserves its name), making the blanking less 'instantaneous'. Also, we may not use a DO...LOOP (reference to the kernel), so the blanking loop is implemented using BEGIN...UNTIL, a little more cumbersome, but still readable; and self-contained. See the definition of blankout in Listing 2. Note that HideCursor is not in the list of 'forbidden' traps.

Third, we cannot intercept events from within the VBL task using EventAvail. This is the reason why in Bob Denny's example from V1#9 a GetNextEvent filter procedure was used. We'll have to do the same thing.

The GNEFilter procedure

A short review of the method to install a GetNextEvent hook:

There is an (undocumented) system global at $29A which contains a location that GetNextEvent jumps to right after removing an Event from the queue. Through this hook, one can install a routine that will be called whenever GetNextEvent receives an event. A pointer to the event record is contained in A1. At the end of this routine, of course, one will have to jump to the location that was contained in $29A.

The GNE hook routine that we are going to install will, each time a non-null event is received, update the last.action counter with the current number of system ticks and repaint the screen if it was blank. In order to keep the definition short, we call traps directly instead of going through the Mach1 'glue' mechanism.

The GNEintfc routine saves most of the registers and restores them after exiting. A local stack (100 bytes) is set up for the Mach1 A6 stack pointer. Some inline assembly code is used to move arguments between the A7 and A6 stacks, and to setup a jump vector at the end of the routine.

The vertical blanking task

one.run is the heart of the vertical blanking task that will be the other part of the CRT saver. It checks whether one minute has passed since the last non-null event and blanks the screen in that case. Furthermore, it then sets a global flag, dark, to indicate to GNEintfc that the screen is dark. At the end of each run, screen blanked or not, the task reschedules itself by resetting the counter in its VBL queue element. Registers are saved and restored, and the routine also uses the local stack. (Note: writing this I realize that in the case that the GetNextEvent filter is interrupted by the vertical blanking and one.run is run during that same interrupt, it will use the same local stack. This might create a problem; so far the CRT saver has not crashed on me. You might think of duplicating the stack area so that the two routines use independent stacks.)

Installation of the CRT saver in the system heap

Of course, the code that we defined so far is local to the Mach1 system and will disappear as soon as Mach1 is exited. If we happened to install the CRT saver before, too bad! Most certainly the system won't survive this kind of abuse. Therefore it remains to copy the routines to a safe place in memory; we'll move them to the system heap before installing. The code that we have to copy is marked by the two headers START and END. The word install.blanker gets a pointer to a chunk of system heap (END - START) bytes long and copies the code to it. The offset is placed into the variable (yes, here we may use a good old variable) blockoffset. All references to the copied routines during installation (for initialization of flags and counters, and for the address passed to the VBL queue element) are made through the original addresses offset by this value.

After the installation (install.blanker and install.GNEfilter), you may leave Mach1, wait one minute and see your screen go dark. Any keypress or mouseclick will make reappear whatever was there.

Turnkeying the CRT saver installer

The word CRTsaver installs the tasks and quits Mach1. This word is used for turnkeying the program:

turnkey CRTsaver CRT

will create an application file CRT, 19K long (Mach1 runtime overhead of 16K) which installs the CRT saver.

Listing 1: CRT saver background task to run in the Mach1 system
( CRT saver task, © 1986 JL for MacTutor)
only forth definitions
also assembler also mac

hex
904 constant currentA5
9EE constant grayRgn
16A constant Ticks
 74 constant screenbits
 10 constant portrect

decimal

( first define port structure )
header screenport
     2 allot ( device )
    14 allot ( bitmap )
     8 allot ( portrect   )
    84 allot ( remaining bytes )


( *** now define background task that does the blanking *** )

variable last.action
variable max.ticks
3600 max.ticks !  ( 1 minute in ticks )

header myevents
    2 allot ( code )
    4 allot ( message )
    4 allot ( when )
    4 allot ( where )
    2 allot ( modifiers )

: relevant.action
    138 ( disk + key + mouse ) 
    ['] myevents call EventAvail
;

: redraw
    call drawmenubar
    call frontWindow
    grayRgn @ call paintBehind
    call showcursor
;

: blankout
    call hidecursor
    ['] screenport call openport
    ['] screenport portrect + call paintrect
    BEGIN relevant.action UNTIL
    ticks @ last.action !
    ['] screenport call setport
    redraw 
;

: monitor.events
    activate
    BEGIN
    PAUSE
    relevant.action 
        IF ticks @ last.action ! THEN
    AGAIN
;

: do.blank
    activate
    BEGIN
    PAUSE
    ticks @ last.action @ - max.ticks @ >
        IF blankout THEN
    AGAIN
;

400 1000 background CRTsaver
CRTsaver build
400 1000 background eventmonitor
eventmonitor build

: saver.start
    ticks @ last.action !
    eventmonitor monitor.events
    CRTsaver do.blank
;

Listing 2: CRT saver, written in Forth, for installation into system 
heap and Mach1 - independent execution

( CRT saver task for installation into VBLTask queue, © 1986 JL for MacTutor 
)
only forth definitions
also assembler also mac

hex
29A constant JGNEFilter
824 constant screenbase
904 constant currentA5
9EE constant grayRgn
16A constant Ticks
 74 constant screenbits
 10 constant portrect
FFFFFFFF constant minusone

.TRAP   _drawmenubar    $A937
.TRAP   _frontwindow    $A924
.TRAP   _paintbehind    $A90D
.TRAP   _newptr,sys     $A51E
.TRAP   _showcursor     $A853

CODE save.regs
    MOVE.W  SR,-(A7)
    MOVEM.L A1-A6/D0-D7,-(A7)
    RTS
END-CODE    MACH

CODE restore.regs
    MOVEM.L (A7)+,A1-A6/D0-D7
    MOVE.W  (A7)+,SR
    RTS
END-CODE    MACH

CODE getA1
    MOVE.L  A1,-(A6)
    RTS
END-CODE    MACH

decimal

header START

( *** we need a local stack after the relocation *** )    
 
header local.stack 100 allot

CODE setup.local.stack
    LEA -8(PC),A6 ( stack grows downward from here )
    RTS
END-CODE

( *** define port structure + some global variables *** )

header screenport
     2 allot ( device )
    14 allot ( bitmap )
     8 allot ( portrect   )
    84 allot ( remaining bytes )

header myevents
    2 allot ( code )
    4 allot ( message )
    4 allot ( when )
    4 allot ( where )
    2 allot ( modifiers )

( *** VBL queue element to be installed *** )

header VBLqelem
    4 allot ( qLink )
    2 allot ( qType )
    4 allot ( vblAddr )
    2 allot ( vblCount )
    2 allot ( vblPhase )

 1 constant vType
 4 constant qType
 6 constant vblAddr
10 constant vblCount
12 constant vblPhase
     
( *** GetNextEvent filter proc definitions *** )

header SavedJGNEFilter 4 allot
header dark  4 allot     
header last.action 4 allot
header max.ticks   4 allot
   3600 ' max.ticks !  ( 1 min in ticks )


: GNEIntfc
    save.regs
    setup.local.stack
    
    getA1 w@ ( event received? )
      IF ticks @ ['] last.action !
        ['] dark @
        IF 
            0 ['] dark !
            _drawmenubar
            CLR.L    -(A7)
            _frontwindow 
            grayrgn @
            MOVE.L   (A6)+,-(A7)
            _paintbehind
            _showcursor
        THEN
      THEN

    ['] SavedJGNEFilter @
    MOVE.L  (A6)+,A0
    restore.regs
    JMP     (A0)
;
    

( *** definitions for VBLtask that does the blanking *** )

: blankout 
    call hidecursor
    screenbase @ 21888 + 
    screenbase @
    BEGIN
        minusone over !
        4 + 2dup < 
    UNTIL 2drop 
    1 ['] dark !
;

: one.run
    save.regs
    setup.local.stack
    ticks @ ['] last.action @ - ['] max.ticks @ >
    ['] dark @ 0=
    AND
    IF  blankout  THEN
    60 ['] VBLqelem vblCount + w! ( reschedule )
    restore.regs
;

header END


( *** install CRT blanker task 'one.run' into VBL queue *** )

variable blockoffset

: get.sys.block  
    ['] end ['] start - 
    MOVE.L (A6)+,D0
    _newptr,sys ( get memory block in system heap )
    MOVE.L A0,-(A6)
;
    
: install.blanker   { | pointer offset -- }
    get.sys.block   -> pointer
    pointer IF
        0 ['] dark !
        ticks @ ['] last.action !
        pointer ['] start -  -> offset
        offset blockoffset !
        ['] start pointer ['] end ['] start - cmove
    ( now make all the moves on the relocated block )
        ['] VBLqelem offset +
        dup qtype + vtype swap w!
        dup vblAddr + ['] one.run offset + swap !
        dup vblCount + 60 swap w!
        dup vblPhase + 5 swap w!
        call Vinstall drop
    ELSE ." Not enough system heap for installation." cr
    THEN
;

: install.GNEfilter
    JGNEFilter @ ['] SavedJGNEFilter blockoffset @ + !
    ['] GNEIntfc blockoffset @ + JGNEFilter !
;

: remove.blanker
    ['] VBLqelem blockoffset @ + call Vremove drop
;

: remove.GNEfilter
    ['] SavedJGNEFilter blockoffset @ +  JGNEFilter ! 
;

: CRTsaver 
    install.blanker
    install.GNEfilter
    bye
;
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

SpamSieve 2.9.38 - Robust spam filter fo...
SpamSieve is a robust spam filter for major email clients that uses powerful Bayesian spam filtering. SpamSieve understands what your spam looks like in order to block it all, but also learns what... Read more
TeamViewer 15.0.8397 - Establish remote...
TeamViewer gives you remote control of any computer or Mac over the Internet within seconds or can be used for online meetings. Find out why more than 200 million users trust TeamViewer! Free for non... Read more
SteerMouse 5.4.3 - Powerful third-party...
SteerMouse is an advanced driver for USB and Bluetooth mice. SteerMouse can assign various functions to buttons that Apple's software does not allow, including double-clicks, modifier clicks,... Read more
Toast Titanium 18.2.1 - The ultimate med...
Roxio Toast Titanium, the leading DVD burner for Mac, makes burning even better, adding Roxio Secure Burn to protect your files on disc and USB in Mac- or Windows-compatible formats. Get more style... Read more
HoudahSpot 5.0.11 - Advanced file-search...
HoudahSpot is a versatile desktop search tool. Use HoudahSpot to locate hard-to-find files and keep frequently used files within reach. HoudahSpot will immediately feel familiar. It works just the... Read more
ClipGrab 3.8.6 - Download videos from Yo...
ClipGrab is a free downloader and converter for YouTube, Vimeo, Facebook and many other online video sites. It converts downloaded videos to MPEG4, MP3 or other formats in just one easy step Version... Read more
ExpanDrive 7.4.0 - Access cloud storage...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
Adobe Dreamweaver CC 2020 20.0 - Build w...
Dreamweaver CC 2020 is available as part of Adobe Creative Cloud for as little as $20.99/month (or $9.99/month if you're a previous Dreamweaver customer). Adobe Dreamweaver CC 2020 allows you to... Read more
Eye Candy 7.2.3.85 - 30 professional Pho...
Eye Candy renders realistic effects that are difficult or impossible to achieve in Photoshop alone, such as Fire, Chrome, and the new Lightning. Effects like Animal Fur, Smoke, and Reptile Skin are... Read more
Sparkle Pro 2.8.5 - Visual website creat...
Sparkle Pro will change your mind if you thought building websites wasn't for you. Sparkle is the intuitive site builder that lets you create sites for your online portfolio, team or band pages, or... Read more

Latest Forum Discussions

See All

Pre-register for Hello Kitty AR: Kawaii...
Hello Kitty — the cute cat that launched a multi-billion-pound franchise — has been brought to life… sort of. Sanrio has teamed up with the Bublar Group to create a new mobile game that uses AR tech to turn the real world into Hello Kitty’s... | Read more »
Gorgeous and tranquil puzzler Spring Fal...
One-man indie studio SPARSE//GameDev has now launched its tranquil puzzler, Spring Falls. It's described as "a peaceful puzzle game about water, erosion, and watching things grow". [Read more] | Read more »
Black Desert Mobile gets an official rel...
Pearl Abyss has just announced that its highly-anticipated MMO, Black Desert Mobile, will launch globally for iOS and Android on December 11th. [Read more] | Read more »
Another Eden receives new a episode, cha...
Another Eden, WFS' popular RPG, has received another update that brings new story content to the game alongside a few new heroes to discover. [Read more] | Read more »
Overdox guide - Tips and tricks for begi...
Overdox is a clever battle royale that changes things up by adding MOBA mechanics and melee combat to the mix. This new hybrid game can be quite a bit to take in at first, so we’ve put together a list of tips to help you get a leg up on the... | Read more »
Roterra Extreme - Great Escape is a pers...
Roterra Extreme – Great Escape has been described by developers Dig-It Games as a mini-sequel to their acclaimed title Roterra: Flip the Fairytale. It continues that game's tradition of messing with which way is up, tasking you with solving... | Read more »
Hearthstone: Battlegrounds open beta lau...
Remember earlier this year when auto battlers were the latest hotness? We had Auto Chess, DOTA Underlords, Chess Rush, and more all gunning for our attention. They all had their own reasons to play, but, at least from where I'm standing, most... | Read more »
The House of Da Vinci 2 gets a new gamep...
The House of Da Vinci launched all the way back in 2017. Now, developer Blue Brain Games is gearing up to deliver a second dose of The Room-inspired puzzling. Some fresh details have now emerged, alongside the game's first official trailer. [Read... | Read more »
Shoot 'em up action awaits in Battl...
BattleBrew Productions has just introduced another entry into its award winning, barrelpunk inspired, BattleSky Brigade series. Whilst its previous title BattleSky Brigade TapTap provided fans with idle town building gameplay, this time the... | Read more »
Arcade classic R-Type Dimensions EX blas...
If you're a long time fan of shmups and have been looking for something to play lately, Tozai Games may have just released an ideal game for you on iOS. R-Type Dimensions EX brings the first R-Type and its sequel to iOS devices. [Read more] | Read more »

Price Scanner via MacPrices.net

13″ 2.4GHz MacBook Pros available for up to $...
Apple has a full line of Certified Refurbished 2019 13″ 2.4GHz 4-Core Touch Bar MacBook Pros available starting at $1529 and up to $300 off MSRP. Apple’s one-year warranty is included, shipping is... Read more
New at T-Mobile: Switch to T-Mobile, and get...
T-Mobile is offering a free 64GB iPhone 8 for new customers who switch to T-Mobile and open a new line of service. Eligible trade-in required, and discount applied over a 24 month period. The fine... Read more
Xfinity Mobile’s Black Friday Apple savings:...
Take $250 off the purchase of any iPhone at Xfinity Mobile with a new line activation, and transfer of phone number to Xfinity Mobile, through December 8, 2019. This includes Apple’s new iPhone 11... Read more
2019 13″ 1.4GHz MacBook Pros available starti...
Apple has a full line of Certified Refurbished 2019 13″ 1.4GHz 4-Core Touch Bar MacBook Pros available starting at $1099 and up to $230 off MSRP. Apple’s one-year warranty is included, shipping is... Read more
Save up to $350 on a 21″ or 27″ iMac with the...
Apple has Certified Refurbished 2019 21″ & 27″ iMacs available starting at $929 and up to $350 off the cost of new models. Apple’s one-year warranty is standard, shipping is free, and each iMac... Read more
Early Holiday 2019 Sale: B&H again offers...
B&H Photo has 10.2″ iPads on sale again for $30 off Apple’s MSRP, starting at $299, as part of their early Holiday 2019 sale. Overnight shipping is free to many addresses in the US: – 10.2″ 32GB... Read more
Apple iMacs on sale today at B&H Photo fo...
B&H Photo has new 2019 21″ and 27″ 5K iMacs on stock today and on sale for up to $150 off Apple’s MSRP. Overnight shipping is free to many locations in the US. These are the same iMacs sold by... Read more
2018 4 and 6-Core Mac minis on sale today for...
Apple resellers are offering new 2018 4-Core and 6-Core Mac minis for $80-$100 off MSRP for a limited time. B&H Photo has the new 2018 4-Core and 6-Core Mac minis on sale for up to $100 off Apple... Read more
Early Holiday 2019 sale at B&H Photo: 12....
B&H Photo has new 12.9″ iPad Pros on sale for up to $120 off Apple’s MSRP as part of their early Holiday 2019 sale. Overnight shipping is free to many addresses in the US: – 12.9″ 64GB WiFi iPad... Read more
8-Core iMac Pro on sale today for $4499 at B...
B&H Photo has the base 8-Core 3.2GHz 32GB/1TB iMac Pro on sale today for $4499 — $500 off Apple’s MSRP. Shipping is free. Their price is the lowest available for a new iMac Pro from any Apple... Read more

Jobs Board

*Apple* Health Benefit Specialist - Call Cen...
Description ** Apple Health Benefit Specialist - Call Center (MAS 3/MACSC)** **Olympia, WA Multiple Positions** *The ideal candidate for this position will have Read more
Hair Stylist - *Apple* Blossom Mall - JCPen...
Hair Stylist - Apple Blossom Mall Location:Winchester, VA, United States- Apple Blossom Mall 1850 Apple Blossom Dr Job ID:1065040Salon Professionals Job Read more
*Apple* Mobility Pro - Best Buy (United Stat...
**747088BR** **Job Title:** Apple Mobility Pro **Job Category:** Store Associates **Store NUmber or Department:** 000297-Reston-Store **Job Description:** At Best Read more
Nurse Practitioner - Field Based (San Bernard...
Nurse Practitioner - Field Based (San Bernardino, CA, Apple Valley, Hesperia) **Location:** **United States** **Requisition #:** PS30312 **Post Date:** Nov 11, 2019 Read more
Best Buy *Apple* Computing Master - Best Bu...
**747061BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Store NUmber or Department:** 000647-Kildeer-Store **Job Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.