PS2 Linux Programming
Capturing The Screen To a File
Introduction
In this tutorial a method
for capturing the screen graphics to a Truevision TGA image file is added to
the SPS2 wrapper class. The image size is determined by the video mode being
used and the image colour depth can be set to either 24 bit RGB or 32 bit RGBA.
The core functionality of the method is taken from a post by Sparky on
Playstation2-linux.com and thanks go to Sparky for this code
(Playstation2-linux.com/projects/sps2demo).
Under normal circumstances
image data is transferred in the host-to-local direction which is to GS memory.
In order to download the frame buffer to main memory, the transmission
direction for image data must be changed to local–to-host. This means that the
transmission direction of both VIF1 and the VIF1 FIFO must be changed to
local-to-host and changed back again at the end of the download. The process
for accomplishing this is described on page 79 of the GS Users Manual and is
embedded within the accompanying tutorial code.
The screen capture
functionality is contained within the method ScreenShot() of the CSPS2Manager
class. It should be noted that this method will only be called occasionally
during the life of the application and is therefore not critical to the
application’s speed – it is therefore not necessary to optimise the operational
speed of this method.
The ScreenShot() method
takes a single parameter, this being either IMAGE_RGBA or IMAGE_RGB for an RGBA
or RGB output file respectively. At the start of ScreenShot() a TGA image file
header is written to the output image file that is opened, the dimensions and
colour depth being determined from the current video mode being used and the
colour depth being requested.
Two 4k pages are allocated
for use by the screen shot method, m_SShotDmaBase points to an area of memory
that is used to build the necessary DMAC chain to send to the GS, and
m_SShotBase points to memory used to hold a horizontal line of the frame buffer
that is downloaded from GS memory.
Once the TGA header is
written to the file, the frame buffer contents are downloaded into SPS2 memory
one horizontal line at a time. The image data is written to the file after
swapping the red and the blue channels. Downloading the frame buffer is
accomplished by the method DownloadVram() which will be investigated below.
DownloadVram() takes the
following 8 parameters:
PDmaBase – is the base address of the memory used to build
the DMAC chain.
PMemBase – is the base address of the memory used to accept
the downloaded frame buffer data.
addr – is the base address of GS memory to be accessed.
This is set to 0 to indicate that the first frame buffer at the start of GS
memory is being downloaded.
bufw – is the frame buffer width in units of 64 pixels.
The buffer width is 640 pixels so bufw is set to 10 (10*64 = 640)
x, y – is the start position of the frame buffer to be
downloaded.
w, h – is the area of the frame buffer to be
downloaded.
Notice that the frame
buffer is accessed from the bottom up and stored in the TGA file in that order
– this is the way that image data must be stored according to the TGA image
file format.
The frame buffer is
downloaded via path 2 which is from the GS via the GIF and VIF1 to main memory.
In order to control and configure this process some VIF codes and GS registers
must be set. These are described below.
Towards the start of the
DownloadVram() method four VIF codes are built into a qward – NOP,
MSKPATH3(0x8000), FLUSHA, DIRECT(6). MSKPATH3(0x8000) disables transfer
processing to the GIF via path 3 after any current transfer, FLUSHA waits for
the state in which there is no transfer request from path3 after the end of any
micro program in VU1 and also waits for the end of any transfer to the GIF from
path 1 and path 2. DIRECT(6) transfers the following 6 qwords of data directly
to the GIF. The purpose of the MSKPATH3 and FLUSHA VIF codes is to ensure that
the VIF and transfer paths are idle before the download process is started.
Following the VIF codes a
GIF packet is constructed to set four registers in A_D mode. The only one that
is new is writing to the FINISH register – data must be written to the FINISH
register (the value does not matter) in order to activate the FINISH event. The
FINISH event is indicated by the FINISH field of the control status register,
CSR becoming 1. In order to “catch” the FINISH event, it is necessary to
disable interrupt generation with a “di” instruction and enable interrupt
generation again (“ei” instruction) after the FINISH event has been detected.
The FINISH event gets lost (and the FINISH Event wait loop never exist) if
interrupts are not disabled.
Once the VIF packet is
constructed, it is sent via DMA transfer to VIF1. The method then waits for the
DMA process to complete and for the GS to complete loading the register data,
this being indicated by the appropriate FINISH event. Finally, the method waits
for the VIF1 FIFO to become idle. At this point it is possible to change the
transmission direction of VIF1 to VIF1-to-memory and the VIF1 FIFO to
local-to-host. The DMA transfer can then be set up to download the appropriate
part of the frame buffer into SPS2 memory. On completion of the download, the
VIF1 and VIF1 FIFO transmission directions are restored to normal and path 3
transfers are re-enabled to complete the process.
In the example code, a
spinning cube is drawn on screen. The screen is captured by pressing L2 on the
controller attached to port 1. Notice that the screen capture method will
determine and use a file name that is free – the method will not overwrite any
existing screen shot files.
A method has been added to
the SPS2 wrapper class to capture the screen to a Truevision TGA image file in
either 24 bit RGB or 32 bit RGBA format.
Dr Henry S Fortuna
University of Abertay
Dundee