Sponsored by BoysStuff.co.uk




Hardware Access Using ARexx - Memory Editing - A Bonus Edition 1.
-----------------------------------------------------------------
  

     

  Hi there readers, it's that AMIGA nutter again... :)

  Although this is not strictly part of my HW Access articles I decided to
  include it for reasons as will be seen below...

  I didn't bother using AmigaBASIC for this task as this can be done easily
  using that interpreter. Plus, it is much easier to make it look prettier
  on screen using AmigaBASIC as opposed to ARexx.

  The ARexx scripts below ARE now already on AMINET, except that the
  MEM-EDIT.rexx IS at Version 00.00.10:-

             http://main.aminet.net/dev/src/MEM-EDIT_AREXX.lha

  So to get the latest version of MEM-EDIT.rexx cut and paste MEM-EDIT.rexx
  from this article, Version 00.00.20 until it is uploaded to AMINET...

  The ARexx script 'Join.rexx' MUST be in the same drawer as MEM-EDIT.rexx.

  System Requirements Are:-
  -------------------------

           Any Classic Amiga, including WinUAE, Version 1.5.3 for me.
           FULL, standard Kickstart 3.0x and Workbench 3.0x or better.
           RexxMast running, and RX in the path.

  (Part 5 of the hardware access series will be in the next magazine issue.)

----------------------------------------------------------------------------

  Overview:-
  ----------

  I have no idea what use this is in the real world but someone asked me to
  write a HEX memory reader and writer using nothing but a standard classic
  AMIGA OS and ARexx. This code will read VALID RAM and ROM addresses and
  write to VALID RAM addresses.

  The guy who asked for it wanted to know how to code in ARexx to do such
  tasks. I said it was easy and within minutes I had written an ARexx :)
  script to read and save a 256(+1) byte memory dump to T: only. After a
  few hours of development Version 00.00.10 of the script below emerged
  and I uploaded it to AMINET and gave it away as Public Domain.

  The original ARexx script that I gave to the guy in question is at the
  end of this article.

  It could be said that this ARexx script is the eqivalent of PEEKing a 256
  byte dump FROM a given VALID memory address and POKEing a SINGLE BYTE
  value TO a given VALID memory address.

  Read the ARexx script to find any further information.

  !!!WARNING!!!

  DO NOT TRY TO READ AND WRITE HARDWARE REGISTERS WITH THIS AREXX CODE!!!

  IT IS POSSIBLE TO READ AND WRITE FROM AND TO SOME OF THE HARDWARE
  REGISTERS USING AREXX, BUT DON'T, AS YOU WILL GENERATE A 'GURU' IF YOU
  DON'T KNOW WHAT YOU ARE DOING!!!

  (I hope you enjoy messing about with coding like I do... :)

  Enjoy finding simple solutions to often very difficult problems... :)

----------------------------------------------------------------------------

  Usage:-
  -------

  Run the code below from the AMIGA Shell using the full window size...

  (The window size is set to 640 x 200 from inside the project icon.
  To set to 640 x 256, change the 200 value in the 'WINDOW' TOOLTYPE inside
  the project icon to 256 and save. This will make it very slightly more
  user friendly. The above archive icon uses IconX as its 'Default Tool'.)

  This code has NO error detection NOR correction!!!
  Invalid values WILL stop the ARexx script at best OR GIVE A COMPLETE
  SYSTEM CRASH AT WORST.

  However it DOES have built in confirmation prompts as a basic means of
  error checking so that IF you DO make a typo, then you can go back to the
  selection screen and try again.

  It will NOT write to ANY drive however UNLESS the INPUTTED values are
  VALID. However it WILL read and write, from and to ENFORCER addresses, so
  DON'T do this unless you know EXACTLY what you are doing!!!
  
  It is assumed that you have extracted the code from this article and
  named it 'MEM-EDIT.rexx'; also that RexxMast is up and running.

  To run the code type 'RX MEM-EDIT.rexx[RETURN/ENTER]' without the quotes
  inside an AMIGA Shell.

  The first screen is just a reminder of some of what is written here.
  Press [RETURN/ENTER] to continue to the next screen.

  You only have five choices, (at present).

  I suggest the you use numbers (2) and (0) until you get used to your
  potential typos and when you feel up to really messing about use numbers
  (1) and (4) also.

  !!!USE NUMBER (3) COMPLETELY AT YOUR OWN RISK!!!

  All SAVED dumps are sent to 'S:' and have the ASCII 'eqivalent' of the
  HEX address you have typed in for the filename. For example 'S:00F80000'.

  The VOLUME 'T:' MUST be available also at ALL times so make sure you have
  'T:' assigned to something, usually a RAMDISK.

  With the limitations of AMIGADOS AND ARexx it IS possible to extract the
  BINARY of the system ROM but this would take hours of messing about.

----------------------------------------------------------------------------

  The code below is at Version 00.00.20 and NOT on AMINET yet... :)

  The MEM-EDIT.rexx ARexx Code:-
  ------------------------------

/* $VER: MEM-EDIT.rexx_Version_00-00-20_Public_Domain_May_2009_B_Walker_G0LCU. */

/* IMPORTANT! THIS IS DEMO CODE ONLY AND THERE IS NO ERROR CORRECTION AT ALL! */

/* This script works on OS2.0x too, NOT just OS3.xx. */

/* This is a DEMO only and dumps a 256 byte dump to 'S:[ADDRESS_TYPED_IN]'. */
/* The AMIGADOS commands 'Type' and 'Delete' MUST be in the C: VOLUME!!! */

/* The 'T:' VOLUME MUST be assigned to a VALID 'VOLUME:Drawer', ('RAM:T'). */

/* It will also WRITE a single byte to a valid memory location, SO BEWARE!!! */

/* There ARE confirmation prompts to act as basic error checks throughout. */

/* Coded by Barry Walker, G0LCU. No copyright as it is offered as PD. */
/* Use ECHO for ordinary strings, and SAY for strings with variables inside. */

/* ---------------------------------------- */

/* Set up a basic startup screen... */
ECHO 'c'x
ECHO '$VER: MEM-EDIT.rexx_Version_00-00-20_Public_Domain_May_2009_B_Walker_G0LCU.'
ECHO ''
ECHO 'A simple hexadecimal memory EDITOR using standard ARexx for classic AMIGAs.'
ECHO 'SAVED memory dumps are to S:[ADDRESS_TYPED_IN] and of 256 bytes in size!'
ECHO ''
ECHO 'This is issued as Public Domain and donated by B.Walker, G0LCU...'
ECHO ''
ECHO 'The characters must be in the range 0123456789ABCDEF and there MUST be two or'
ECHO 'eight of them. Addresses and byte values are in hexadecimal AND leading zeros'
ECHO 'ARE important!!!'
ECHO ''
ECHO '!!!WARNING!!!'
ECHO '-------------'
ECHO ''
ECHO 'There is NO error correction at all, therefore any INPUTTING typos WILL cause'
ECHO 'ARexx to stop with an error report, OR, GENERATE A SERIOUS SYSTEM CRASH!!!'
ECHO ''
ECHO 'BE VERY AWARE OF THIS!!!'
CALL keyboardhold

/* ---------------------------------------- */

/* Set up general variables. */
bytevalue = '00'
dumpstartaddress = '00FC0000'
dumpstring = ''
jobtodo = '0'
savefile = 'myfile'
simplecheck = 'Y'

/* Note the variable, [dumpstartaddresshex], below, MUST be a string */
/* representation of a hexadecimal, preferably, EVEN address. */
/* The leading zero(s) and trailing 'x' ARE BOTH IMPORTANT!!! */
/* The DEMO address, '00FC0000', is inside the classic AMIGA ROM area. */
dumpstartaddresshex = '00FC0000'x

/* Similarly for the byte variable, [realbytehex], below. */
realbytehex = '00'x

/* ---------------------------------------- */

/* Enter a hexadecimal address from '00000000' to '00FFFF00'. */
DO FOREVER
ECHO 'c'x
ECHO 'Hexadecimal memory reader and writer...'
ECHO ''
ECHO 'Type a number then [RETURN/ENTER]:-'
ECHO '-----------------------------------'
ECHO ''
ECHO '                (1) for a 256 byte memory dump to disk.'
ECHO '                (2) for a 256 byte memory read only.'
ECHO '                (3) for a SINGLE BYTE WRITE to memory.'
ECHO '                (4) for joining 2 or more binary files together.'
ECHO ''
ECHO '                (0) to QUIT.'
PULL jobtodo
IF jobtodo = '1' THEN CALL saveandread
IF jobtodo = '2' THEN CALL readonly
IF jobtodo = '3' THEN CALL writebyte
IF jobtodo = '4' THEN ADDRESS COMMAND 'RX Join.rexx'
IF jobtodo = '0' THEN CALL getout
END

/* ---------------------------------------- */

/* Read a memory dump and auto-save to S:[ADDRESS_TYPED_IN]... */
saveandread:
CALL enteraddress
IF simplecheck ~= 'Y' THEN RETURN

/* Open up a filename to save to. */
OPEN(savefile, 'S:'||dumpstartaddress, 'W')
/* Save the filename... */
WRITECH(savefile, dumpstring)
/* Immediately close the file when dumped. */
CLOSE(savefile)

/* ---------------------------------------- */

/* Do a simple print to the screen of what is saved in hexadecimal */
/* ASCII readable format using AMIGADOS command 'Type'. */
readonly:
IF jobtodo = '2' THEN CALL enteraddress
IF simplecheck ~= 'Y' THEN RETURN
ECHO 'c'x
IF jobtodo = '1' THEN SAY 'File saved to the S: VOLUME as "[S:]'||dumpstartaddress||'"...'
IF jobtodo = '2' THEN SAY 'Memory start address is at $'||dumpstartaddress||', plus offset shown.'
ECHO ''
ECHO 'ASCII display of the hexadecimal dump of a 256 byte string...'
ECHO ''
IF jobtodo = '1' THEN ADDRESS COMMAND 'C:Type S:'||dumpstartaddress||' HEX'
IF jobtodo = '2' THEN CALL temporaryread
CALL keyboardhold
RETURN

/* ---------------------------------------- */

/* Do a temporary save to T: and read the contents... */
temporaryread:
/* Open up a temporary filename to save to... */
OPEN(savefile, 'T:'||dumpstartaddress, 'W')
/* Save the filename... */
WRITECH(savefile, dumpstring)
/* Immediately close the file when dumped. */
CLOSE(savefile)

/* Display contents of dump saved to T:. */
ADDRESS COMMAND 'C:Type T:'||dumpstartaddress||' HEX'
/* Delete the file when displayed. */
ADDRESS COMMAND 'C:Delete T:'||dumpstartaddress||' QUIET'
RETURN

/* ---------------------------------------- */

/* Manual hexadecimal memory address entry point... */
enteraddress:
ECHO 'c'x
ECHO 'Enter a VALID hexadecimal address, for example, 00F80000[RETURN/ENTER]:-'
ECHO ''
PULL dumpstartaddress
ECHO ''
SAY 'Is "'||dumpstartaddress||'" correct? (Y/N[RETURN/ENTER]):-'
ECHO ''
PULL simplecheck
IF simplecheck = 'Y' THEN CALL enteraddresscont
RETURN

/* If typed value is correct then carry on. */
enteraddresscont:
/* Convert the value to the contents of the address pointer... */
dumpstartaddresshex = X2C(dumpstartaddress)

/* Fetch the 256 byte binary string. */
dumpstring = IMPORT(dumpstartaddresshex, 256)
RETURN

/* ---------------------------------------- */

/* Write a single byte to memory. */
/* Ask for confirmation first! */
writebyte:
ECHO 'c'x
ECHO '!!!WARNING!!!'
ECHO ''
ECHO 'WRITING TO MEMORY CAN CAUSE A SERIOUS SYSTEM FALIURE!!!'
ECHO ''
ECHO 'ARE YOU SURE YOU WANT TO CONTINUE?, (Y/N[RETURN/ENTER]):-'
ECHO ''
PULL simplecheck
IF simplecheck = 'Y' THEN CALL writebytecont
RETURN

/* Continue after confirmation... */
writebytecont:
CALL enteraddress
IF simplecheck ~= 'Y' THEN RETURN

/* Display where the memory write will be. */
ECHO 'c'x
SAY 'Memory address to write to is $'||dumpstartaddress||'.'
ECHO ''
ECHO 'Enter byte value in hexadecimal, for example, 7F[RETURN/ENTER]:-'
ECHO ''
PULL bytevalue
ECHO ''
SAY 'Is "'||bytevalue||'" correct? (Y/N[RETURN/ENTER]):-'
ECHO ''
PULL simplecheck
IF simplecheck = 'Y' THEN CALL dowritebyte
RETURN

/* Do the write to memory!!! */
dowritebyte:
/* Convert the ASCII byte to the real HEX value. */
realbytehex = X2C(bytevalue)

/* Write a single hexadecimal byte to memory. */
EXPORT(dumpstartaddresshex, realbytehex, 1)

/* Read the BYTE, in LONGWORD form, from the changed address. */
dumpstring = IMPORT(dumpstartaddresshex, 4)

/* Display on screen the four contiguous bytes. */
ECHO 'c'x
SAY 'Address changed is $'||dumpstartaddress||', plus offset shown...'
ECHO ''
SAY '0000:  '||C2X(dumpstring)||'  for four bytes, (longword), only!'
CALL keyboardhold
RETURN

/* ---------------------------------------- */

/* Stop the display until the [RETURN/ENTER] key is pressed... */
keyboardhold:
ECHO ''
ECHO 'Press [RETURN/ENTER] to continue:-'
PULL jobtodo
RETURN

/* ---------------------------------------- */

/* Clean exit... */
getout:
ECHO 'c'x
ECHO 'Click the CLOSE gadget to QUIT...'
ECHO ''
EXIT(0)
/* Program end. */

----------------------------------------------------------------------------

  This is a typical HEX dump to disk starting at KS 3.1x ROM address
  $00F80000...

0000: 11144EF9 00F800D2 0000FFFF 00280044    ..Nù.ø.Ò.....(.D     
0010: 0028000A FFFFFFFF 00414D49 47412052    .(.......AMIGA R     
0020: 4F4D204F 70657261 74696E67 20537973    OM Operating Sys     
0030: 74656D20 616E6420 4C696272 61726965    tem and Librarie     
0040: 7300436F 70797269 67687420 A9203139    s.Copyright © 19     
0050: 38352D31 39393320 00436F6D 6D6F646F    85-1993 .Commodo     
0060: 72652D41 6D696761 2C20496E 632E2000    re-Amiga, Inc. .     
0070: 416C6C20 52696768 74732052 65736572    All Rights Reser     
0080: 7665642E 00332E31 20524F4D 20006578    ved..3.1 ROM .ex     
0090: 65632E6C 69627261 72790065 78656320    ec.library.exec      
00A0: 34302E31 30202831 352E372E 3933290D    40.10 (15.7.93).     
00B0: 0A004E71 4E714AFC 00F800B6 00F8370E    ..NqNqJü.ø.¶.ø7.     
00C0: 02280969 00F8008E 00F8009B 00F804AC    .(.i.ø...ø...ø.¬     
00D0: 4E704FF8 040041FA FF2872FF 75017B00    NpOø..Aú.(r.u.{.     
00E0: DA986402 528551C9 FFF851CA FFF44BFA    Ú.d.R.QÉ.øQÊ.ôKú     
00F0: 001A41FA FF0C43F9 00F00000 B3C8670A    ..Aú..Cù.ð..³Èg.     

  This would be saved to the S: VOLUME as [S:]00F80000...

----------------------------------------------------------------------------

  Join.rexx Usage:-
  -----------------

  IMPORTANT NOTE:- There is NO error detection OR correction in this code.

  On program startup a default window is opened. Two lines are printed to
  this window, (not inclding the line numbers)...

  1) $VER: Join.rexx_Public_Domain_01-06-2009_B.Walker_G0LCU.
  2) Double click on the first file to join...

  A file requester is opened to the default S: VOLUME with the file
  Startup-Sequence ready to be OK'd if required.

  Double clicking on ANY file at all will automatically save it to the S:
  VOLUME as S:TEMPFILE. If you click 'Cancel' the the script WILL generate
  an error BUT WILL carry on... Irrespective however the next lines printed
  are...

  3) File saved as S:TEMPFILE...
  4) Double click on the next file to join...

  Another file requester is opened for the next file to join to S:TEMPFILE.
  Again double clicking on ANY file at all will join that file in FRONT of
  S:TEMPFILE and is saved to the S: VOLUME as S:BINARY.BIN. Also again
  clicking on 'Cancel' WILL generate an error as before.

  The next two lines printed are...

  5) File saved as S:BINARY.BIN...
  6) Press [RETURN/ENTER] to CONTINUE, or, Q[RETURN/ENTER] to QUIT:-

  Pressing [RETURN/ENTER] will cycle through this code again BUT IF you
  want to add to the BINARY.BIN file during the CURRENT session, just
  double click on S:BINARY.BIN as the FIRST file and for the SECOND file
  that you want in FRONT of the BINARY.BIN, (now a new S:TEMPFILE), just
  double click on that too.
  Pressing Q[RETURN/ENTER] starts the Quitting proceedure...

  The window is cleared and the lines printed are...

  7) Files now joined as T:BINARY.BIN...
  8) Delete the S:TEMPFILE file...
  9) Delete the S:BINARY.BIN file...
 10) Quitting...

  After a few seconds the window closes down.

  There is now a copy of S:BINARY.BIN in the T: VOLUME as T:BINARY.BIN
  so that you can save it elsewhere and/or rename it your leisure.

  In the 'S' drawer of this archive is a file 1KB.BIN. This is a joining
  of the files 00F80300, 00F80200, 00F80100 and 00F80000 in three loops.
  This was saved as T:BINARY.BIN, renamed to T:1KB.BIN and copied to the
  above drawer to view. It is obviously the first 1KB of the ROM 3.1x image.

  The default tool inside the 'Join.rexx' project icon is More. Just change
  the default tool to suit your needs, for example RX to run the srcipt.

  Below is the ORIGINAL ARexx code so that there is a reference to look back
  at when viewing any current versions that may appear... :)

----------------------------------------------------------------------------

  The Join.rexx ARexx Code:-
  --------------------------

/* A DEMO simple file joining utility to join at least two files together. */
/* Original idea copyright, (C)2009, B.Walker. G0LCU. */
/* Issued as Public Domain and you can do as you please with this code. */

/* To join addresses together start with the highest HEX dump */
/* first and work downwards. */

/* Similarly with textfiles 'Last In First Out'... :) */

/* Pick the last, (address?), file needed from the S: VOLUME... */
/* IMPORTANT!!! DURING THE CURRENT SESION IF 'S:BINARY.BIN' EXISTS THEN */
/* THIS BECOMES THE NEW LAST ADDRESS/FILE!!! */

/* Set up any variables... */
  quitkey = ''

/* Use default window for prompts... */
/* This will loop to generate a manual binary dump... */
  DO FOREVER
    ECHO 'c'x
    ECHO '$VER: Join.rexx_Version_00-00-20_Public_Domain_01-06-2009_B.Walker_G0LCU.'
    ECHO 'Double click on the first file to join...'
    ADDRESS COMMAND 'C:Join `C:RequestFile DRAWER S: FILE Startup-Sequence` AS S:TEMPFILE'
    ECHO 'File saved as S:TEMPFILE...'
/* Now pick the next lower or earlier, (address?), file from the S: VOLUME... */
    ECHO 'Double click on the next file to join...'
    ADDRESS COMMAND 'C:Join `C:RequestFile DRAWER S: FILE Startup-Sequence` S:TEMPFILE AS S:BINARY.BIN'
    ECHO 'File saved as S:BINARY.BIN...'
    ECHO 'Press [RETURN/ENTER] to CONTINUE, or, Q[RETURN/ENTER] to QUIT:-'
    ECHO''
    PULL quitkey
    IF quitkey = 'Q' THEN CALL getout
  END

getout:
  ECHO 'c'x
/* Copy the file 'S:BINARY.BIN' to the 'T:' VOLUME as 'T:BINARY.BIN'... */
  ADDRESS COMMAND 'C:Copy S:BINARY.BIN TO T:BINARY.BIN'
  ECHO 'Files now joined as T:BINARY.BIN...'
  ECHO ''
  ECHO 'Delete the S:TEMPFILE file...'
/* Delete the temporary file 'S:TEMPFILE'... */
  ADDRESS COMMAND 'C:Delete S:TEMPFILE QUIET'
  ECHO 'Delete the S:BINARY.BIN file...'
/* Delete the temporary file 'S:BINARY.BIN'... */
  ADDRESS COMMAND 'C:Delete S:BINARY.BIN QUIET'
  ECHO ''
  ECHO 'Quitting...'
/* Clean exit... */
  EXIT(0)

  That's all there is to it... :)

----------------------------------------------------------------------------

  Lastly; now don't you dare laugh at this...... :D

  This was the original code that was sent to the anonymous guy in question.
  It was saved to T: instead as it was just a taster...

  So before you say it, I realised my intital error of using WRITELN instead
  of WRITECH, anyhow I have picked that one up now... :)

  Original ARexx Code:-
  ---------------------

/* This is a DEMO only and dumps a 256+1 byte dump to T:MEMDUMP. */
/* I'll let this go as PD for the club. */
/* The EOF will add an extra character "0A" at the end! */
/* This is NOT a bug and can be cured if so required. */
/* By Barry Walker, G0LCU. No copyright as it is offered as PD. */

/* Set up variables. */
dumplength = 256

/* Note this variable MUST be a string representation of a */
/* hexadecimal EVEN address. The leading zeros and trailing "x" */
/* ARE IMPORTANT!!! NOTE the demo address is in ROM. */
dumpstartaddress = '00F80000'x

/* Generate a NULL string to save. */
dumpstring = ''

/* Fetch the 256 byte binary string. */
dumpstring = IMPORT(dumpstartaddress, dumplength)

/* Open up a filename to save to. */
OPEN('myfile', 'T:MEMDUMP', 'W')
/* Save the filename... */
WRITELN('myfile', dumpstring)
/* Immediately close the file when dumped - REMEMBER - the file */
/* adds an extra character "0A" at the end!!! */
CLOSE('myfile')

/* Do a simple print to the screen of what is saved in hexadecimal */
/* ASCII readable format. */
ECHO C2X(dumpstring)

/* Clean exit... */
EXIT(0)
/* Program end. */

  That's all there is to it folks.
  Enjoy finding simple solutions to often very difficult problems... :)

  I will be adding MEM-CLEAR.rexx, MEM-FILL.rexx, MEM-COPY.rexx and etc...

  How about a 680x0 disassembler using ARexx and a standard FULL AMIGA
  OS3.0x install?

----------------------------------------------------------------------------

  The archive is Public Domain/Emailware and you may modify it/them as you
  please for your OWN experiments.

----------------------------------------------------------------------------

                                IMPORTANT:-
                                -----------

    The Legal Stuff:-
    -----------------

    These programs are Public Domain and no profit will be made from them,
    also all of the files must remain unaltered and intact including this
    one. The author is not responsible for any damage to, or loss of, or
    failure of equipment or data caused in any way by the use of these
    programs. There is NO warranty with the use of these software releases
    and YOU USE THEM AT YOUR OWN RISK.

----------------------------------------------------------------------------

    Testing Evaluation:-
    --------------------

    An A1200 in 2MB, 6MB and 10MB modes using trapdoor memory AND/Or PCMCIA
    memory expansions. WinUAE version 1.5.3 in classic Workbench 3.0x mode. 

    All test conditions were/are running STANDARD 3.0x, and using standard
    ~topaz 8~ fonts throughout.

    I have no idea what a strange configuration setup will create so refer
    to the ~The Legal Stuff~ above.

----------------------------------------------------------------------------

                                 WARNING.
                                 --------

  1) DISCONNECT any faulty equipment under test from the MAINS supply.
  2) If a DC supply is used do NOT reverse polarity the connections.
  3) Do NOT power up any electronic item until it is safe to do so.
  4) CHECK and RECHECK all of your construction and repair work thoroughly.
  5) Handle ALL tools used with care.
  6) Beware of ALL types of solvents, glues and etching fluids.
  7) NEVER leave a soldering iron switched on unattended.
  8) KEEP everything OUT of the reach of small children.
  9) Switch OFF the AMIGA before disconnecting or connecting any hardware.
 10) And finally read 1) to 9) again.

----------------------------------------------------------------------------

   Contact:-
   ---------

   Mr Barry Walker, G0LCU,

   Email:-     wisecracker@tesco.net
   URL:-       http://homepages.tesco.net/wisecracker/G0LCU.HTM

   Author of the ~TestGear?~ projects in the ~docs/hard~ drawer of AMINET.

----------------------------------------------------------------------------

   A very useful HardWare related site, (C) Anthony Hoffman, for
   modifications, schematics, repairs and the like is:-

                          http://amiga.serveftp.net/

============================================================================



© RIYAN Productions

AmigaZ Logo