The Map Area
The map area was designed for graphics purposes. However, no graphics routines were implemented other than a simple horizontal line-write that PipeDream uses. The map is the small area on the right hand edge of the screen to display a picture of what a page looks like in PipeDream, when printed. This region consists of between 0 and 256 pixels across by 64 pixels down. It is theoretically possible to have a 624 by 64 Hires screen, but with current information, graphics are limited to the map area only. It is possible, with extreme care, to write directly to the map memory, by accessing the HIRES0 character set, see the "Hardware layout of the map" section for further details.
Once you have opened a window for the map, say window '1', the system automatically updates the contents of the map to the defined window 50 times a second by the Blink array chip. The map memory is simply hard-wired, and everthing written to it will immediatly be reflected on the screen (if opened via the OS_Map call).
The calls provided here, only allows you to write to the map area, not to read back from it. If you need to know about the contents of the map area, then you should keep a copy of what you write have written to it. The width of the map is limited to 96 pixels in an unexpanded machine. The actual width will always be a multiple of 8, although the widths used by the OS_Map call will be on less than this, ie. 63 refers to an actual width of 64 pixels, numbered 0 to 63. The map call has the following specification:
Â
RST 20H, DEFW $F406 IN:            BC = reason code            MP_WR ($01)            write a line to the map            MP_DEF ($02)           define a map using the Panel default width            MP_GRA ($03)           define a map of specific width MP_MEM ($05)  define a map of specific width and associate to application segment OUT, if call successful:            Fc = 0 OUT, if call failed:            Fc = 1            A = error code:                        RC_BAD ($04), bad parameters (errors are generally ignored)                        RC_UNK ($03), value of BC is not valid
The various calls to manipulate the map area on the simple line based interface is found at the OS_Map call specification in the System Calls Reference section.
If you are adventurous, have a look at the following examples. Since the map is hardwired, anything written to it will automatically be reflected in the map window. It is possible, and very easy to write graphical routines once the physical layout of the map memory is defined.Â
The hardware layout of the map
The map on the Z88 have been designed for a maximum of 256 pixels wide and 64 pixels high graphical area. Even though it is a graphical area, its basic organisation is a character based matrix, where each 'character' is defined by eight column bytes from top to bottom. Each 'line' is then defined by the 'characters'. This is why the width of the map area is defined in multiple of 8 (bits). The following illustrates the memory map organisation:
<graphics_base>, (0,0)Â
Â
           y columns:
x rows:    <byte0>    <byte8>    <byte16>   ...        <mapwidth>
           <byte1>    <byte9>    ...
           <byte2>    <byte10>   ...
           <byte3>    <byte11>   ...
           <byte4>    <byte12>   ...
           <byte5>    ...        ...
           <byte6>    ...        ...
           <byte7>    <byte15>   <byte(x)*8+y>
line y:Â Â Â Â <byte <mapwidth>*8*(y div 8)>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <graphics_end>
The above illustration defines the organisation for 'lines' of 'characters'. The width of the map is defined in byte boundaries. The following formula defines the byte position from the base of the map area, defined by a simple (x,y) pixel position, where (0,0) is at the upper left corner of <byte0>.
           linedist = (y div 8) * <mapwidth>  ; each line is 8 * <mapwidth>
           rowdist = (x div 8) * 8           ; step 8 bytes pr. 8 pixels
           coldist = y mod 8                 ; somewhere in a 'character'
           bytepos = linedist + rowdist + coldist
Given a pixel coordinate of (x,y) = (10,4), and a map of 80 pixels wide (10 bytes), the formula would look like this:
           linedist = (4 div 8) * <10>        =>         0
           rowdist = (10 div 8) * 8          =>         8
           coldist = (4 mod 8)               =>         4
           bytepos = 12
which is at <byte12>. The pixel position within the byte (ie. bit position) is simply:
           pixelpos = 7 - (x mod 8)           =>         5
which fits: the second bit (seen from left) in the second byte row.Â
Â
Example
The following two examples manipulates the map area directly, thereby avoiding the relatively large system overhead of the OS_Map call. Here, you read/write directly to the map area. The two examples show how easy graphics can be implemented on the Z88, as long as you play by the rules and avoid writing beyond the boundaries of the map.
First the base address of the map is fetched, then the memory is paged into segment 2 and the base address of the map is stored at (BASE_GRAPHICS). The following example routine will return an address and a corresponding bit position of the address in the map from a virtual (x,y) coordinate. This is the basic algorithm for manipulating graphics in the map area. The Standard Library contains a complete set of library graphics routines to plot points, draw lines, sprites and scroll the map area contents. All source files are included for evaluation and improvement. These two routines are an extract:
Â
include "memory.def"           ; memory call definitions include "map.def"              ; map call definitions include "screen.def"           ; low level screen call definitions ; Open graphics window '1', static size of 256x64 pixels, and bind graphics ; memory into segment 2. NOTE: Only expanded machines may open a 256 pixels ; wide map. ; .openmap          ld     a,'1'        ; use window '1' for graphics         ld     B, MS_S2          ld     C, MP_MEM          ld     hl,255         oz     OS_Map        ; create a map of 256 pixels          rst    OZ_Mpb        ; and bind map memory to segment 2            ld    (base_graphics),hl ; initialize base address of hires0            ret ; This routine returns the address and bit position of a pixel coordinate (x,y) ; ; in: hl = (x,y) coordinate of pixel (h,l) ; ; out: de = address of pixel byte ; a = bit number of byte where pixel is to be placed ; fz = 1 if bit number is 0 of pixel position ; ; registers changed after return: ; ......hl/ixiy same ; afbcde../.... different ; .pixeladdr ld  b,l            srl b            srl b            srl b             ; linedist = y div 8 * 256            ld  a,h            and @11111000     ; rowdist = x div 8 * 8            ld  c,a           ; bc = linedist + rowdist            ld  a,l            and @00000111     ; coldist = y mod 8            ld  de,(base_graphics) ; pointer to base of graphics area            ld  e,a           ; coldist = graphicsarea + coldist            ld  a,h            ex  de,hl            add hl,bc         ; bytepos = linedist + rowdist + coldist            ex  de,hl            and @00000111     ; a = x mod 8            xor @00000111     ; a = 7 - a            ret