ScummVM API documentation
Graphics

Description

The way graphics work in the OSystem class is meant to make it possible for game frontends to implement everything they need in an efficient manner. The downside of this is that it may be rather complicated for backend authors to fully understand and implement the semantics of the OSystem interface.

The graphics visible to the user in the end are actually composed of three layers: the game graphics, the overlay graphics, and the mouse.

First, there are the game graphics. The methods in this section deal with them exclusively. In particular, the size of the game graphics is defined by a call to initSize(), and copyRectToScreen() blits the data in the current pixel format into the game layer. Let W and H denote the width and height of the game graphics.

Before the user sees these graphics, the backend may apply some transformations to it. For example, they may be scaled to better fit the visible screen or aspect ratio correction may be performed (see kFeatureAspectRatioCorrection). As a result of this, a pixel of the game graphics may occupy a region bigger than a single pixel on the screen. p_w and p_h are defined to be the width and, respectively, height of a game pixel on the screen.

In addition, there is a horizontal and vertical "shake offset" (as defined by setShakePos) that are used in some games to provide a shaking effect. Note that shaking is applied to all three layers, i.e. also to the overlay and the mouse. The shake offsets are denoted by XS and YS.

Putting this together, a pixel (x,y) of the game graphics is transformed to a rectangle of height p_h and width p_w appearing at position (p_w * (x + XS), p_hw * (y + YS)) on the real screen. In addition, a backend may choose to offset everything, e.g. to center the graphics on the screen.

The next layer is the overlay. It is composed over the game graphics. Historically, the overlay size had always been a multiple of the game resolution. For example, if the game resolution was 320x200 and the user selected a 2x scaler and did not enable aspect ratio correction, it had a size of 640x400. An exception was the aspect ratio correction, which did allow for non multiples of the vertical resolution of the game screen. Currently, the overlay size does not need to have any relation to the game resolution though, for example the overlay resolution might be the same as the physical screen resolution. The overlay is forced to a 16 bpp mode right now.

Finally, there is the mouse layer. This layer does not have to actually exist within the backend – it all depends on how a backend chooses to implement mouse cursors. However, in the default SDL backend, it really is a separate layer. The mouse can have a palette of its own, if the backend supports it.

Graphics do not need to be thread-safe and in fact most/all backends using OpenGL are not. So do not try to call any of these functions from a timer and/or audio callback (like readBuffer of AudioStreams).

Classes

struct  OSystem::GraphicsMode
 

Enumerations

enum  OSystem::GfxModeFlags { OSystem::kGfxModeNoFlags = 0, OSystem::kGfxModeRender3d = (1 << 0) }
 
enum  OSystem::TransactionError {
  OSystem::kTransactionSuccess = 0, OSystem::kTransactionAspectRatioFailed = (1 << 0), OSystem::kTransactionFullscreenFailed = (1 << 1), OSystem::kTransactionModeSwitchFailed = (1 << 2),
  OSystem::kTransactionSizeChangeFailed = (1 << 3), OSystem::kTransactionFormatNotSupported = (1 << 4), OSystem::kTransactionFilteringFailed = (1 << 5), OSystem::kTransactionStretchModeSwitchFailed = (1 << 6),
  OSystem::kTransactionShaderChangeFailed = (1 << 7), OSystem::kTransactionVSyncFailed = (1 << 8)
}
 

Functions

virtual const GraphicsModeOSystem::getSupportedGraphicsModes () const
 
virtual int OSystem::getDefaultGraphicsMode () const
 
virtual bool OSystem::setGraphicsMode (int mode, uint flags=kGfxModeNoFlags)
 
bool OSystem::setGraphicsMode (const char *name)
 
virtual int OSystem::getGraphicsMode () const
 
Graphics::PixelFormat OSystem::getScreenFormat () const
 
Common::List< Graphics::PixelFormatOSystem::getSupportedFormats () const
 
virtual Common::Array< uint > OSystem::getSupportedAntiAliasingLevels () const
 
virtual OpenGL::ContextType OSystem::getOpenGLType () const
 
virtual bool OSystem::setShader (const Common::Path &fileName)
 
virtual const GraphicsModeOSystem::getSupportedStretchModes () const
 
virtual int OSystem::getDefaultStretchMode () const
 
virtual bool OSystem::setStretchMode (int mode)
 
bool OSystem::setStretchMode (const char *name)
 
virtual int OSystem::getStretchMode () const
 
virtual uint OSystem::getDefaultScaler () const
 
virtual uint OSystem::getDefaultScaleFactor () const
 
virtual bool OSystem::setScaler (uint mode, int factor)
 
virtual bool OSystem::setScaler (const char *name, int factor)
 
virtual uint OSystem::getScaler () const
 
virtual uint OSystem::getScaleFactor () const
 
virtual void OSystem::initSize (uint width, uint height, const Graphics::PixelFormat *format=nullptr)=0
 
virtual void OSystem::initSizeHint (const Graphics::ModeList &modes)
 
virtual int OSystem::getScreenChangeID () const
 
virtual void OSystem::beginGFXTransaction ()
 
virtual TransactionError OSystem::endGFXTransaction ()
 
virtual int16 OSystem::getHeight ()=0
 
virtual int16 OSystem::getWidth ()=0
 
virtual PaletteManagerOSystem::getPaletteManager ()=0
 
virtual float OSystem::getHiDPIScreenFactor () const
 
virtual void OSystem::copyRectToScreen (const void *buf, int pitch, int x, int y, int w, int h)=0
 
virtual Graphics::SurfaceOSystem::lockScreen ()=0
 
virtual void OSystem::unlockScreen ()=0
 
virtual void OSystem::fillScreen (uint32 col)=0
 
virtual void OSystem::fillScreen (const Common::Rect &r, uint32 col)=0
 
virtual void OSystem::updateScreen ()=0
 
virtual void OSystem::setShakePos (int shakeXOffset, int shakeYOffset)=0
 
virtual void OSystem::setFocusRectangle (const Common::Rect &rect)
 
virtual void OSystem::clearFocusRectangle ()
 
virtual void OSystem::saveScreenshot ()
 

Enumeration Type Documentation

◆ GfxModeFlags

Enumerator
kGfxModeNoFlags 

No flags.

kGfxModeRender3d 

Indicate 3D hardware-accelerated in-game GFX.

◆ TransactionError

This type can save the different errors which can happen while changing GFX config values inside GFX transactions.

endGFXTransaction returns an ORed combination of the '*Failed' values if any problem occurs. It returns '0' on success.

See also
endGFXTransaction
Enumerator
kTransactionSuccess 

Everything fine (use EQUAL check for this one!)

kTransactionAspectRatioFailed 

Failed switching aspect ratio correction mode

kTransactionFullscreenFailed 

Failed switching fullscreen mode

kTransactionModeSwitchFailed 

Failed switching the GFX graphics mode (setGraphicsMode)

kTransactionSizeChangeFailed 

Failed switching the screen dimensions (initSize)

kTransactionFormatNotSupported 

Failed setting the color format

kTransactionFilteringFailed 

Failed setting the filtering mode

kTransactionStretchModeSwitchFailed 

Failed setting the stretch mode

kTransactionShaderChangeFailed 

Failed setting the shader

kTransactionVSyncFailed 

Failed switching vsync mode

Function Documentation

◆ getSupportedGraphicsModes()

virtual const GraphicsMode* OSystem::getSupportedGraphicsModes ( ) const
inlinevirtual

Retrieve a list of all graphics modes supported by this backend.

This can be both video modes as well as graphic filters/scalers. It is completely up to the backend maintainer to decide what is appropriate here and what not. The list is terminated by an all-zero entry.

Returns
List of supported graphics modes.

Reimplemented in OSystem_Wii, OSystem_N64, OSystem_DS, OSystem_PSP, and ModularGraphicsBackend.

◆ getDefaultGraphicsMode()

virtual int OSystem::getDefaultGraphicsMode ( ) const
inlinevirtual

Return the ID of the 'default' graphics mode. What exactly this means is up to the backend. This mode is set by the client code when no user overrides are present (i.e. if no custom graphics mode is selected using the command line or a config file).

Returns
ID of the 'default' graphics mode.

Reimplemented in OSystem_Wii, OSystem_N64, OSystem_DS, OSystem_PSP, and ModularGraphicsBackend.

◆ setGraphicsMode() [1/2]

virtual bool OSystem::setGraphicsMode ( int  mode,
uint  flags = kGfxModeNoFlags 
)
inlinevirtual

Switch to the specified graphics mode.

If switching to the new mode fails, this method returns false.

The flag 'kGfxModeRender3d' is optional. It allows to switch to 3D-only rendering mode. In this mode, the game engine is allowed to use OpenGL(ES) directly.

Parameters
modeID of the new graphics mode.
flagsFlags for the new graphics mode.
Returns
True if the switch was successful, false otherwise.

Reimplemented in OSystem_Wii, OSystem_N64, OSystem_iOS7, OSystem_DS, OSystem_PSP, and ModularGraphicsBackend.

◆ setGraphicsMode() [2/2]

bool OSystem::setGraphicsMode ( const char *  name)

Switch to the graphics mode with the given name.

If name is unknown, or if switching to the new mode fails, this method returns false.

Parameters
nameName of the new graphics mode.
Returns
True if the switch was successful, false otherwise.
Note
This is implemented using the setGraphicsMode(int) method, as well as getSupportedGraphicsModes() and getDefaultGraphicsMode(). In particular, backends do not have to overload this!

◆ getGraphicsMode()

virtual int OSystem::getGraphicsMode ( ) const
inlinevirtual

Determine which graphics mode is currently active.

Returns
ID of the active graphics mode.

Reimplemented in OSystem_Wii, OSystem_N64, OSystem_DS, OSystem_PSP, and ModularGraphicsBackend.

◆ getSupportedAntiAliasingLevels()

virtual Common::Array<uint> OSystem::getSupportedAntiAliasingLevels ( ) const
inlinevirtual

Retrieve a list of supported levels of anti-aliasing.

Anti-aliasing only works when using one of the hardware-accelerated renderers. An empty list means anti-aliasing is not supported.

◆ getOpenGLType()

virtual OpenGL::ContextType OSystem::getOpenGLType ( ) const
inlinevirtual

Return the chosen OpenGL type.

This function works even when a 2D graphical manager is active and let to select a proper renderer before changing mode. Implementation having feature kFeatureOpenGLForGame are expected to override this function.

Returns
the OpenGL type of context which is supported.

◆ setShader()

virtual bool OSystem::setShader ( const Common::Path fileName)
inlinevirtual

Load the specified shader.

If loading the new shader fails, this method returns false.

Parameters
fileNodeFile node of the new shader.
Returns
True if the switch was successful, false otherwise.

Reimplemented in ModularGraphicsBackend.

◆ getSupportedStretchModes()

virtual const GraphicsMode* OSystem::getSupportedStretchModes ( ) const
inlinevirtual

Retrieve a list of all stretch modes supported by this backend.

It is completely up to the backend maintainer to decide what is appropriate here and what not. The list is terminated by an all-zero entry.

Returns
a list of supported stretch modes

Reimplemented in OSystem_DS, and ModularGraphicsBackend.

◆ getDefaultStretchMode()

virtual int OSystem::getDefaultStretchMode ( ) const
inlinevirtual

Return the ID of the 'default' stretch mode.

What exactly this means is up to the backend. This mode is set by the client code when no user overrides are present (i.e. if no custom stretch mode is selected using the command line or a config file).

Returns
ID of the 'default' graphics mode.

Reimplemented in OSystem_DS, and ModularGraphicsBackend.

◆ setStretchMode() [1/2]

virtual bool OSystem::setStretchMode ( int  mode)
inlinevirtual

Switch to the specified stretch mode.

If switching to the new mode fails, this method returns false.

Parameters
modeID of the new graphics mode.
Returns
True if the switch was successful, false otherwise.

Reimplemented in OSystem_DS, and ModularGraphicsBackend.

◆ setStretchMode() [2/2]

bool OSystem::setStretchMode ( const char *  name)

Switch to the stretch mode with the given name.

If name is unknown, or if switching to the new mode fails, this method returns false.

Parameters
nameName of the new stretch mode.
Returns
True if the switch was successful, false otherwise.
Note
This is implemented using the setStretchMode(int) method, as well as getSupportedStretchModes() and getDefaultStretchMode(). In particular, backends do not have to overload this!

◆ getStretchMode()

virtual int OSystem::getStretchMode ( ) const
inlinevirtual

Determine which stretch mode is currently active.

Returns
ID of the active stretch mode.

Reimplemented in OSystem_DS, and ModularGraphicsBackend.

◆ getDefaultScaler()

virtual uint OSystem::getDefaultScaler ( ) const
inlinevirtual

Return the ID of the 'default' scaler.

This mode is set by the client code when no user overrides are present (i.e. if no custom scaler is selected using the command line or a config file).

Returns
ID of the 'default' scaler.

Reimplemented in ModularGraphicsBackend.

◆ getDefaultScaleFactor()

virtual uint OSystem::getDefaultScaleFactor ( ) const
inlinevirtual

Return the 'default' scale factor.

This mode is set by the client code when no user overrides are present (i.e. if no custom scaler is selected using the command line or a config file).

Returns
The 'default' scale factor.

Reimplemented in ModularGraphicsBackend.

◆ setScaler() [1/2]

virtual bool OSystem::setScaler ( uint  mode,
int  factor 
)
inlinevirtual

Switch to the specified scaler.

If switching to the new mode fails, this method returns false.

Parameters
modeID of the new scaler.
factorThe scale factor to use
Returns
True if the switch was successful, false otherwise.

Reimplemented in ModularGraphicsBackend.

◆ setScaler() [2/2]

virtual bool OSystem::setScaler ( const char *  name,
int  factor 
)
inlinevirtual

Switch to the scaler with the given name.

If name is unknown, or if switching to the new mode fails, this method returns false.

Parameters
nameName of the new scaler.
factorThe scale factor to use
Returns
True if the switch was successful, false otherwise.

Reimplemented in BaseBackend.

◆ getScaler()

virtual uint OSystem::getScaler ( ) const
inlinevirtual

Determine which scaler is currently active.

Returns
ID of the active stretch mode.

Reimplemented in ModularGraphicsBackend.

◆ getScaleFactor()

virtual uint OSystem::getScaleFactor ( ) const
inlinevirtual

Determine which scale factor is currently active.

Returns
The active scale factor.

Reimplemented in ModularGraphicsBackend.

◆ initSize()

virtual void OSystem::initSize ( uint  width,
uint  height,
const Graphics::PixelFormat format = nullptr 
)
pure virtual

Set the size and color format of the virtual screen.

Typical sizes include:

  • 320x200 (e.g. for most SCUMM games, and Simon)
  • 320x240 (e.g. for FM-TOWN SCUMM games)
  • 640x480 (e.g. for Curse of Monkey Island)

This is the resolution for which the client code generates data. This is not necessarily equal to the actual display size. For example, a backend may magnify the graphics to fit on the screen (see also the GraphicsMode), stretch the data to perform aspect ratio correction, or shrink it to fit on small screens (in cell phones).

Typical formats include:

  • CLUT8 (e.g. 256 color, for most games)
  • RGB555 (e.g. 16-bit color, for later SCUMM HE games)
  • RGB565 (e.g. 16-bit color, for Urban Runner)

This is the pixel format for which the client code generates data. It is not necessarily equal to the hardware pixel format. For example, a backend may perform color lookup of 8-bit graphics before pushing a screen to hardware, or correct the ARGB color order.

Parameters
widthNew virtual screen width.
heightNew virtual screen height.
formatNew virtual screen pixel format.

Implemented in OSystem_Wii, OSystem_N64, N3DS::OSystem_3DS, OSystem_Dreamcast, OSystem_DS, ModularGraphicsBackend, and OSystem_PSP.

◆ initSizeHint()

virtual void OSystem::initSizeHint ( const Graphics::ModeList modes)
inlinevirtual

Send a list of graphics modes to the backend so it can make a decision about the best way to set up the display hardware.

Engines that switch between different virtual screen sizes during a game should call this function prior to any call to initSize. Engines that use only a single screen size do not need to call this function.

Parameters
modesList of graphics modes the engine will probably use.

Reimplemented in ModularGraphicsBackend.

◆ getScreenChangeID()

virtual int OSystem::getScreenChangeID ( ) const
inlinevirtual

Return an int value that is changed whenever any screen parameters (like the resolution) change, i.e. whenever EVENT_SCREEN_CHANGED is sent.

You can track this value in your code to detect screen changes in case you do not have full control over the event loop(s) being used (like the GUI code).

Returns
Integer that can be used to track screen changes.
Note
Backends that generate EVENT_SCREEN_CHANGED events must overload this method appropriately.

Reimplemented in N3DS::OSystem_3DS, and ModularGraphicsBackend.

◆ beginGFXTransaction()

virtual void OSystem::beginGFXTransaction ( )
inlinevirtual

Begin a new GFX transaction, which is a sequence of GFX mode changes.

The idea behind GFX transactions is to make it possible to activate several different GFX changes at once as a "batch" operation. For example, assume we are running in 320x200 with a 2x scaler (thus using 640x400 pixels in total). Now, we want to switch to 640x400 with the 1x scaler. Without transactions, we have to choose whether we want to first switch the scaler mode, or first to 640x400 mode. In either case, depending on the backend implementation, problems may occur. For example, the window might briefly switch to 320x200 or 1280x800. Using transactions, this can be avoided.

Note
Transaction support is optional, and the default implementations of the relevant methods simply do nothing.
See also
endGFXTransaction

Reimplemented in N3DS::OSystem_3DS, and ModularGraphicsBackend.

◆ endGFXTransaction()

virtual TransactionError OSystem::endGFXTransaction ( )
inlinevirtual

End (and thereby commit) the current GFX transaction.

See also
beginGFXTransaction
kTransactionError
Returns
ORed combination of TransactionError values or 0 on success.

Reimplemented in N3DS::OSystem_3DS, and ModularGraphicsBackend.

◆ getHeight()

virtual int16 OSystem::getHeight ( )
pure virtual

Return the currently set virtual screen height.

See also
initSize
Returns
Currently set virtual screen height.

Implemented in OSystem_Wii, N3DS::OSystem_3DS, OSystem_N64, OSystem_Dreamcast, OSystem_DS, ModularGraphicsBackend, and OSystem_PSP.

◆ getWidth()

virtual int16 OSystem::getWidth ( )
pure virtual

Return the currently set virtual screen width.

See also
initSize
Returns
Currently set virtual screen width.

Implemented in OSystem_Wii, N3DS::OSystem_3DS, OSystem_N64, OSystem_Dreamcast, OSystem_DS, ModularGraphicsBackend, and OSystem_PSP.

◆ getPaletteManager()

virtual PaletteManager* OSystem::getPaletteManager ( )
pure virtual

Return the palette manager singleton.

For more information, see PaletteManager.

Implemented in OSystem_Wii, OSystem_N64, N3DS::OSystem_3DS, OSystem_DS, ModularGraphicsBackend, OSystem_Dreamcast, and OSystem_PSP.

◆ getHiDPIScreenFactor()

virtual float OSystem::getHiDPIScreenFactor ( ) const
inlinevirtual

Return the scale factor for HiDPI screens. Returns 1 for non-HiDPI screens, or if HiDPI display is not supported by the backend.

Reimplemented in ModularGraphicsBackend.

◆ copyRectToScreen()

virtual void OSystem::copyRectToScreen ( const void *  buf,
int  pitch,
int  x,
int  y,
int  w,
int  h 
)
pure virtual

Blit a bitmap to the virtual screen.

The real screen will not immediately be updated to reflect the changes. Client code must call updateScreen to ensure any changes are visible to the user. This can be used to optimize drawing and reduce flicker.

If the current pixel format has one byte per pixel, the graphics data uses 8 bits per pixel, using the palette specified via setPalette. If more than one byte per pixel is in use, the graphics data uses the pixel format returned by getScreenFormat.

Parameters
bufBuffer containing the graphics data source.
pitchPitch of the buffer (number of bytes in a scanline).
xx coordinate of the destination rectangle.
yy coordinate of the destination rectangle.
wWidth of the destination rectangle.
hHeight of the destination rectangle.
Note
The specified destination rectangle must be completly contained in the visible screen space, and must be non-empty. If not, a backend may or may not perform clipping, trigger an assert, or silently corrupt memory.
See also
updateScreen
getScreenFormat

Implemented in OSystem_Wii, OSystem_N64, N3DS::OSystem_3DS, OSystem_Dreamcast, OSystem_DS, OSystem_PSP, and ModularGraphicsBackend.

◆ lockScreen()

virtual Graphics::Surface* OSystem::lockScreen ( )
pure virtual

Lock the active screen framebuffer and return a Graphics::Surface representing it.

The caller can then perform arbitrary graphics transformations on the framebuffer (blitting, scrolling, etc.). Must be followed by a matching call to unlockScreen(). Code that is calling this should make sure to only lock the framebuffer for the shortest time possible, as the whole system is potentially stalled while the lock is active.

Returns
0 if an error occurs. Otherwise, a surface with the pixel format described by getScreenFormat is returned.

The returned surface must not be deleted by the client code.

See also
getScreenFormat

Implemented in OSystem_Wii, OSystem_N64, N3DS::OSystem_3DS, OSystem_DS, OSystem_Dreamcast, OSystem_PSP, and ModularGraphicsBackend.

◆ unlockScreen()

virtual void OSystem::unlockScreen ( )
pure virtual

Unlock the screen framebuffer, and mark it as dirty, i.e. during the next updateScreen() call, the whole screen will be updated.

Implemented in OSystem_Wii, OSystem_N64, N3DS::OSystem_3DS, OSystem_DS, OSystem_Dreamcast, OSystem_PSP, and ModularGraphicsBackend.

◆ fillScreen() [1/2]

virtual void OSystem::fillScreen ( uint32  col)
pure virtual

Fill the screen with the given color value.

Implemented in ModularGraphicsBackend, and BaseBackend.

◆ fillScreen() [2/2]

virtual void OSystem::fillScreen ( const Common::Rect r,
uint32  col 
)
pure virtual

Fill the specified area of the screen with the given color value.

Implemented in ModularGraphicsBackend, and BaseBackend.

◆ updateScreen()

virtual void OSystem::updateScreen ( )
pure virtual

Flush the whole screen, i.e. render the current content of the screen framebuffer to the display.

This method may be called very often by engines. Backends are hence supposed to only perform any redrawing if it is necessary and otherwise return immediately. See https://wiki.scummvm.org/index.php/HOWTO-Backends#updateScreen.28.29_method

Implemented in OSystem_Wii, OSystem_N64, N3DS::OSystem_3DS, OSystem_Dreamcast, OSystem_DS, ModularGraphicsBackend, and OSystem_PSP.

◆ setShakePos()

virtual void OSystem::setShakePos ( int  shakeXOffset,
int  shakeYOffset 
)
pure virtual

Set current shake position, a feature needed for screen effects in some engines.

The effect causes the displayed graphics to be shifted downwards and rightwards by the specified offsets (the offsets can be negative to shift upwards or leftwards). The area at the border of the screen which is moved into view by this (for example at the bottom when moving upward) is filled with black. This does not cause any graphic data to be lost. To restore the original view, the game engine only has to call this method again with offset equal to zero. No calls to copyRectToScreen are necessary.

Parameters
shakeXOffsetShake x offset.
shakeYOffsetShake y offset.
Note
This is currently used in the SCUMM, QUEEN, KYRA, SCI, DREAMWEB, SUPERNOVA, TEENAGENT, TOLTECS, ULTIMA, and PETKA engines.

Implemented in OSystem_Wii, OSystem_N64, N3DS::OSystem_3DS, OSystem_Dreamcast, OSystem_DS, ModularGraphicsBackend, and OSystem_PSP.

◆ setFocusRectangle()

virtual void OSystem::setFocusRectangle ( const Common::Rect rect)
inlinevirtual

Set the area of the screen that has the focus.

For example, when a character is speaking, they will have the focus. This allows for pan-and-scan style views where the backend can follow the speaking character or area of interest on the screen.

The backend is responsible for clipping the rectangle and deciding how best to zoom the screen to show any shape and size rectangle the engine provides.

Parameters
rectRectangle on the screen to be focused on.
See also
clearFocusRectangle

Reimplemented in N3DS::OSystem_3DS, OSystem_DS, and ModularGraphicsBackend.

◆ clearFocusRectangle()

virtual void OSystem::clearFocusRectangle ( )
inlinevirtual

Clear the focus set by a call to setFocusRectangle().

This allows the engine to clear the focus when no particular area of the screen has the focus.

See also
setFocusRectangle

Reimplemented in N3DS::OSystem_3DS, OSystem_DS, and ModularGraphicsBackend.

◆ saveScreenshot()

virtual void OSystem::saveScreenshot ( )
inlinevirtual

Instruct the backend to capture a screenshot of the current screen.

The backend can persist it the way it considers appropriate.

Reimplemented in ModularGraphicsBackend.