BACKENDS: ATARI: Rework

- Atari TT support
- all video and audio is now handled via XBIOS
- reworked IKBD handling using Kbdvbase vectors, esp. Kbdvec()
- video uses proper triple buffer
- arbitrary game screen size support
- many fixes and optimizations
This commit is contained in:
Miro Kropacek 2023-06-15 00:05:13 +02:00
parent 8bf928c0d8
commit 5537759c53
22 changed files with 1719 additions and 1214 deletions

View File

@ -19,17 +19,11 @@
*
*/
.globl _asm_screen_tt_save
.globl _asm_screen_falcon_save
.global _asm_screen_tt_save
.global _asm_screen_falcon_save
.globl _asm_screen_tt_restore
.globl _asm_screen_falcon_restore
.globl _asm_screen_set_tt_palette
.globl _asm_screen_set_falcon_palette
.globl _asm_screen_set_vram
.globl _asm_screen_set_scp_res
.global _asm_screen_tt_restore
.global _asm_screen_falcon_restore
.text
@ -97,15 +91,6 @@ falcon_save_loop:
move.w 0xffff8266.w,(a0)+ | f_s
move.w 0xffff8260.w,(a0)+ | st_s
| install custom VBL handler
move sr,-(sp)
or #0x700,sr
move.l 0x70.w,old_vbl
move.l #vbl,0x70.w
move (sp)+,sr
movem.l (sp)+,d2-d7/a2
rts
@ -132,14 +117,6 @@ _asm_screen_tt_restore:
_asm_screen_falcon_restore:
movem.l d2-d7/a2,-(sp)
| uninstall custom VBL handler
move sr,-(sp)
or #0x700,sr
move.l old_vbl,0x70.w
move (sp)+,sr
bsr wait_vbl | avoid flickering
lea save_video,a0
@ -199,152 +176,16 @@ falcon_restore_loop:
movem.l (sp)+,d2-d7/a2
rts
| extern void asm_screen_set_tt_palette(const uint16 pPalette[256]);
|
_asm_screen_set_tt_palette:
move.l (4,sp),a0
lea 0xffff8400.w,a1
moveq #256/2-1,d0
set_tt_palette_loop:
move.l (a0)+,(a1)+
dbra d0,set_tt_palette_loop
rts
| extern void asm_screen_set_falcon_palette(const byte pPalette[256*3]);
|
_asm_screen_set_falcon_palette:
move.l (4,sp),a0
lea pending_palette,a1
move.w #256-1,d0
set_falcon_palette_loop:
clr.l d1
move.w (a0)+,d1
swap d1
move.b (a0)+,d1
move.l d1,(a1)+
dbra d0,set_falcon_palette_loop
addq.w #1,has_pending_palette
rts
| extern void asm_screen_set_vram(const void* pScreen);
|
_asm_screen_set_vram:
move.l (4,sp),pending_vram
addq.w #1,has_pending_vram
rts
| void asm_screen_set_scp_res(const void* pScp);
|
_asm_screen_set_scp_res:
move.l (4,sp),a0
lea (122,a0),a0
lea pending_scp,a1
moveq #(158-122)/4-1,d0
set_scp_res_loop:
move.l (a0)+,(a1)+
dbra d0,set_scp_res_loop
addq.w #1,has_pending_scp
rts
wait_vbl:
move.w #0x25,-(sp) | Vsync()
trap #14 |
addq.l #2,sp |
rts
.ascii "XBRA"
.ascii "SCUM"
old_vbl:
dc.l 0
vbl:
movem.l d0-d1/a0-a1,-(sp)
addq.l #1,0x0462.w | _vbclock
addq.l #1,0x0466.w | _frclock
tst.w has_pending_scp
beq.b vbl_no_pending_scp
lea pending_scp,a0
move.l (a0)+,0xffff8282.w
move.l (a0)+,0xffff8286.w
move.l (a0)+,0xffff828a.w
move.l (a0)+,0xffff82a2.w
move.l (a0)+,0xffff82a6.w
move.l (a0)+,0xffff82aa.w
move.w (a0)+,0xffff820a.w
move.w (a0)+,0xffff82c0.w
clr.w 0xffff8266.w
tst.w (a0)+
bne.b vbl_st
vbl_falcon:
move.w (a0)+,0xffff8266.w
bra.b vbl_skip
vbl_st: addq.l #1,a0
move.b (a0)+,0xffff8260.w
vbl_skip:
move.w (a0)+,0xffff82c2.w
move.w (a0)+,0xffff8210.w
clr.w has_pending_scp
vbl_no_pending_scp:
tst.w has_pending_vram
beq.b vbl_no_pending_vram
move.l pending_vram,d0
move.l d0,d1
lsr.w #8,d0
move.l d0,0xffff8200.w
move.b d1,0xffff820d.w
clr.w has_pending_vram
vbl_no_pending_vram:
tst.w has_pending_palette
beq.b vbl_no_pending_palette
lea pending_palette,a0
lea 0xffff9800.w,a1
moveq #256/2-1,d0
vbl_falcon_palette_loop:
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
dbra d0,vbl_falcon_palette_loop
clr.w has_pending_palette
vbl_no_pending_palette:
movem.l (sp)+,d0-d1/a0-a1
rte
.bss
.even
has_pending_scp:
ds.w 1
has_pending_vram:
ds.w 1
has_pending_palette:
ds.w 1
pending_scp:
ds.b 158-122 | pending SCP resolution data
pending_vram:
ds.l 1 | pending vram pointer
pending_palette:
ds.l 256 | pending palette
save_pal:
ds.l 256+16/2 | old colours (sized for falcon+ste palette)
save_video:

View File

@ -44,27 +44,6 @@ void asm_screen_tt_restore(void);
*/
void asm_screen_falcon_restore(void);
/**
* Set Atari TT palette.
* @param pPalette 256 palette entries (0000 RRRR GGGG BBBB)
*/
void asm_screen_set_tt_palette(const uint16 pPalette[256]);
/**
* Set Atari Falcon palette.
* @param pPalette 256 palette entries (RRRRRRRR GGGGGGGG BBBBBBBB)
*/
void asm_screen_set_falcon_palette(const byte pPalette[256*3]);
/**
* Set Atari TT/Falcon video base.
*/
void asm_screen_set_vram(const void* pScreen);
/**
* Set Atari Falcon Videl resolution (Screenspain's SCP format).
*/
void asm_screen_set_scp_res(const void* pScp);
}
#endif

View File

@ -31,7 +31,8 @@
#define SV_VERSION ((volatile long*)0x8001007C)
inline static bool hasSuperVidel() {
static bool hasSuperVidel = VgetMonitor() == MON_VGA && Getcookie(C_SupV, NULL) == C_FOUND;
// this works also on the TT
static bool hasSuperVidel = Getcookie(C_SupV, NULL) == C_FOUND && VgetMonitor() == MON_VGA;
return hasSuperVidel;
}

View File

@ -29,7 +29,6 @@
#include <mint/osbind.h>
#include "backends/graphics/atari/atari-graphics-superblitter.h"
#include "backends/graphics/atari/videl-resolutions.h"
#include "common/debug.h" // error() & warning()
#include "common/scummsys.h"
@ -47,12 +46,6 @@ public:
else
warning("SV_XBIOS has the pmmu boost disabled, set 'pmmu_boost = true' in C:\\SV.INF");
// patch SPSHIFT for SuperVidel's BPS8C
for (byte *p : {scp_320x200x8_vga, scp_320x240x8_vga, scp_640x400x8_vga, scp_640x480x8_vga}) {
uint16 *p16 = (uint16*)(p + 122 + 30);
*p16 |= 0x1000;
}
// using virtual methods so must be done here
allocateSurfaces();
}

View File

@ -71,25 +71,50 @@ private:
// used for pixel reading; two common mistakes:
// 1. (subRect.left, subRect.bottom) = beginning of the next line *including the offset*
// 2. (subRect.right, subRect.bottom) = even worse, end of the *next* line, not current one
if (subRect.width() == dstSurface.w) {
asm_c2p1x1_8(
(const byte*)srcSurface.getBasePtr(subRect.left, subRect.top),
(const byte*)srcSurface.getBasePtr(subRect.right, subRect.bottom-1),
(byte*)dstSurface.getBasePtr(destX, destY));
} else {
const byte *pChunky = (const byte *)srcSurface.getBasePtr(subRect.left, subRect.top);
const byte *pChunkyEnd = (const byte *)srcSurface.getBasePtr(subRect.right, subRect.bottom-1);
const uint32 bitsPerPixel = dstSurface.format.isCLUT8() || dstSurface.format == PIXELFORMAT_RGB332 ? 8 : 4;
const uint32 screenPitch = dstSurface.pitch * bitsPerPixel/8;
byte *pScreen = (byte *)dstSurface.getPixels() + destY * screenPitch + destX * bitsPerPixel/8;
if (bitsPerPixel == 8) {
if (srcSurface.pitch == subRect.width()) {
if (srcSurface.pitch == dstSurface.pitch) {
asm_c2p1x1_8(pChunky, pChunkyEnd, pScreen);
return;
} else if (srcSurface.pitch == dstSurface.pitch/2) {
asm_c2p1x1_8_tt(pChunky, pChunkyEnd, pScreen, screenPitch);
return;
}
}
asm_c2p1x1_8_rect(
(const byte*)srcSurface.getBasePtr(subRect.left, subRect.top),
(const byte*)srcSurface.getBasePtr(subRect.right, subRect.bottom-1),
pChunky, pChunkyEnd,
subRect.width(),
srcSurface.pitch,
(byte*)dstSurface.getBasePtr(destX, destY),
dstSurface.pitch);
pScreen,
screenPitch);
} else {
// compare unmodified dst pitch
if (srcSurface.pitch == subRect.width() && srcSurface.pitch == dstSurface.pitch) {
asm_c2p1x1_4(pChunky, pChunkyEnd, pScreen);
return;
}
asm_c2p1x1_4_rect(
pChunky, pChunkyEnd,
subRect.width(),
srcSurface.pitch,
pScreen,
screenPitch);
}
}
void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface, const Graphics::Surface &bgSurface,
const Graphics::Surface &srcSurface, int destX, int destY,
const Common::Rect &subRect, uint32 key, const byte srcPalette[256*3]) const override {
void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface, const Graphics::Surface &srcSurface,
int destX, int destY, const Common::Rect &subRect, uint32 key,
const Graphics::Surface &bgSurface, const byte srcPalette[256*3]) const override {
Common::Rect backgroundRect(destX, destY, destX + subRect.width(), destY + subRect.height());
// ensure that background's left and right lie on a 16px boundary and double the width if needed
@ -116,34 +141,7 @@ private:
cachedSurface.copyRectToSurface(bgSurface, 0, 0, backgroundRect);
// copy cursor
if (cachedSurface.format == PIXELFORMAT_RGB332) {
assert(srcSurface.format == PIXELFORMAT_CLUT8);
// Convert CLUT8 to RGB332 palette and do copyRectToSurfaceWithKey() at the same time
const byte *src = (const byte*)srcSurface.getBasePtr(subRect.left, subRect.top);
byte *dst = (byte*)cachedSurface.getBasePtr(deltaX, 0);
const int16 w = subRect.width();
const int16 h = subRect.height();
for (int16 y = 0; y < h; ++y) {
for (int16 x = 0; x < w; ++x) {
const uint32 color = *src++;
if (color != key) {
*dst++ = (srcPalette[color*3 + 0] & 0xe0)
| ((srcPalette[color*3 + 1] >> 3) & 0x1c)
| ((srcPalette[color*3 + 2] >> 6) & 0x03);
} else {
dst++;
}
}
src += (srcSurface.pitch - w);
dst += (cachedSurface.pitch - w);
}
} else {
cachedSurface.copyRectToSurfaceWithKey(srcSurface, deltaX, 0, subRect, key);
}
convertRectToSurfaceWithKey(cachedSurface, srcSurface, deltaX, 0, subRect, key, srcPalette);
copyRectToSurface(
dstSurface,
@ -151,14 +149,6 @@ private:
backgroundRect.left, backgroundRect.top,
Common::Rect(cachedSurface.w, cachedSurface.h));
}
void alignRect(const Graphics::Surface &srcSurface, Common::Rect &rect) const override {
// align on 16px
rect.left &= 0xfff0;
rect.right = (rect.right + 15) & 0xfff0;
if (rect.right > srcSurface.w)
rect.right = srcSurface.w;
}
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@
#include "backends/graphics/graphics.h"
#include <mint/osbind.h>
#include <mint/ostruct.h>
#include <vector>
#include "common/events.h"
@ -67,12 +68,18 @@ public:
void showOverlay(bool inGUI) override;
void hideOverlay() override;
bool isOverlayVisible() const override { return _overlayVisible; }
Graphics::PixelFormat getOverlayFormat() const override { return PIXELFORMAT_RGB332; }
Graphics::PixelFormat getOverlayFormat() const override {
#ifndef DISABLE_FANCY_THEMES
return _tt ? PIXELFORMAT_RGB121 : PIXELFORMAT_RGB332;
#else
return PIXELFORMAT_RGB121;
#endif
}
void clearOverlay() override;
void grabOverlay(Graphics::Surface &surface) const override;
void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
int16 getOverlayHeight() const override { return 480; }
int16 getOverlayWidth() const override { return 640; }
int16 getOverlayWidth() const override { return _vgaMonitor ? 640 : 640*1.2; }
bool showMouse(bool visible) override;
void warpMouse(int x, int y) override;
@ -89,12 +96,16 @@ public:
protected:
const Graphics::PixelFormat PIXELFORMAT_CLUT8 = Graphics::PixelFormat::createFormatCLUT8();
const Graphics::PixelFormat PIXELFORMAT_RGB332 = Graphics::PixelFormat(1, 3, 3, 2, 0, 5, 2, 0, 0);
const Graphics::PixelFormat PIXELFORMAT_RGB121 = Graphics::PixelFormat(1, 1, 2, 1, 0, 3, 1, 0, 0);
typedef void* (*AtariMemAlloc)(size_t bytes);
typedef void (*AtariMemFree)(void *ptr);
void allocateSurfaces();
void freeSurfaces();
void convertRectToSurfaceWithKey(Graphics::Surface &dstSurface, const Graphics::Surface &srcSurface,
int destX, int destY, const Common::Rect &subRect, uint32 key,
const byte srcPalette[256*3]) const;
enum class GraphicsMode : int {
DirectRendering = 0,
@ -117,12 +128,27 @@ protected:
GraphicsState _pendingState{ (GraphicsMode)getDefaultGraphicsMode() };
private:
enum {
// maximum screen dimensions
SCREEN_WIDTH = 640,
SCREEN_HEIGHT = 480
// use std::vector as its clear() doesn't reset capacity
using DirtyRects = std::vector<Common::Rect>;
enum CustomEventAction {
kActionToggleAspectRatioCorrection = 100,
};
enum SteTtRezValue {
kRezValueSTLow = 0, // 320x200@4bpp, ST palette
kRezValueSTMid = 1, // 640x200@2bpp, ST palette
kRezValueSTHigh = 2, // 640x400@1bpp, ST palette
kRezValueTTLow = 7, // 320x480@8bpp, TT palette
kRezValueTTMid = 4, // 640x480@4bpp, TT palette
kRezValueTTHigh = 6 // 1280x960@1bpp, TT palette
};
int16 getMaximumScreenHeight() const { return 480; }
int16 getMaximumScreenWidth() const { return _tt ? 320 : (_vgaMonitor ? 640 : 640*1.2); }
bool updateScreenInternal(const Graphics::Surface &srcSurface, const DirtyRects &dirtyRects);
virtual AtariMemAlloc getStRamAllocFunc() const {
return [](size_t bytes) { return (void*)Mxalloc(bytes, MX_STRAM); };
}
@ -130,29 +156,16 @@ private:
return [](void *ptr) { Mfree(ptr); };
}
// use std::vector as its clear() doesn't reset capacity
using DirtyRects = std::vector<Common::Rect>;
enum CustomEventAction {
kActionToggleAspectRatioCorrection = 100,
};
void setVidelResolution() const;
bool updateDirect();
bool updateBuffered(const Graphics::Surface &srcSurface, const DirtyRects &dirtyRects);
virtual void copyRectToSurface(Graphics::Surface &dstSurface,
const Graphics::Surface &srcSurface, int destX, int destY,
const Common::Rect &subRect) const {
dstSurface.copyRectToSurface(srcSurface, destX, destY, subRect);
}
virtual void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface, const Graphics::Surface &bgSurface,
const Graphics::Surface &srcSurface, int destX, int destY,
const Common::Rect &subRect, uint32 key, const byte srcPalette[256*3]) const {
dstSurface.copyRectToSurfaceWithKey(srcSurface, destX, destY, subRect, key);
virtual void copyRectToSurfaceWithKey(Graphics::Surface &dstSurface, const Graphics::Surface &srcSurface,
int destX, int destY, const Common::Rect &subRect, uint32 key,
const Graphics::Surface &bgSurface, const byte srcPalette[256*3]) const {
convertRectToSurfaceWithKey(dstSurface, srcSurface, destX, destY, subRect, key, srcPalette);
}
virtual void alignRect(const Graphics::Surface &srcSurface, Common::Rect &rect) const {}
void cursorPositionChanged() {
if (_overlayVisible) {
@ -176,7 +189,27 @@ private:
}
}
void cursorVisibilityChanged() {
if (_overlayVisible) {
_screen[OVERLAY_BUFFER]->cursorVisibilityChanged = true;
} else {
_screen[FRONT_BUFFER]->cursorVisibilityChanged
= _screen[BACK_BUFFER1]->cursorVisibilityChanged
= _screen[BACK_BUFFER2]->cursorVisibilityChanged
= true;
}
}
int getOverlayPaletteSize() const {
#ifndef DISABLE_FANCY_THEMES
return _tt ? 16 : 256;
#else
return 16;
#endif
}
bool _vgaMonitor = true;
bool _tt = false;
bool _aspectRatioCorrection = false;
bool _oldAspectRatioCorrection = false;
@ -184,7 +217,7 @@ private:
enum PendingScreenChange {
kPendingScreenChangeNone = 0,
kPendingScreenChangeOverlay = 1<<0,
kPendingScreenChangeMode = 1<<0,
kPendingScreenChangeScreen = 1<<1,
kPendingScreenChangePalette = 1<<2
};
@ -198,44 +231,48 @@ private:
BUFFER_COUNT
};
struct Screen {
Screen(AtariGraphicsManager *manager, int width, int height, const Graphics::PixelFormat &format);
~Screen();
void reset(int width, int height) {
cursorPositionChanged = true;
cursorSurfaceChanged = false;
clearDirtyRects();
oldCursorRect = Common::Rect();
// erase old screen
surf.fillRect(Common::Rect(surf.w, surf.h), 0);
// set new dimensions
surf.pitch = width;
surf.w = width;
surf.h = height;
class Palette {
public:
void clear() {
memset(data, 0, sizeof(data));
}
void addDirtyRect(Common::Rect rect);
uint16 *const tt = reinterpret_cast<uint16*>(data);
_RGB *const falcon = reinterpret_cast<_RGB*>(data);
private:
byte data[256*4] = {};
};
struct Screen {
Screen(AtariGraphicsManager *manager, int width, int height, const Graphics::PixelFormat &format, const Palette *palette);
~Screen();
void reset(int width, int height, int bitsPerPixel);
void addDirtyRect(const Graphics::Surface &srcSurface, Common::Rect rect);
void clearDirtyRects() {
dirtyRects.clear();
_fullRedraw = false;
fullRedraw = false;
}
const bool &fullRedrawPending = _fullRedraw;
Graphics::Surface surf;
const Palette *palette;
bool cursorPositionChanged = true;
bool cursorSurfaceChanged = false;
bool cursorVisibilityChanged = false;
DirtyRects dirtyRects = DirtyRects(512); // reserve 512 rects
bool fullRedraw = false;
Common::Rect oldCursorRect;
int rez = -1;
int mode = -1;
Graphics::Surface *const offsettedSurf = &_offsettedSurf;
private:
static constexpr size_t ALIGN = 16; // 16 bytes
bool _fullRedraw = false;
AtariGraphicsManager *_manager;
Graphics::Surface _offsettedSurf;
};
Screen *_screen[BUFFER_COUNT] = {};
Screen *_workScreen = nullptr;
@ -294,8 +331,8 @@ private:
int hotspotY;
} _cursor;
byte _palette[256*3] = {};
byte _overlayPalette[256*3] = {};
Palette _palette;
Palette _overlayPalette;
};
#endif

View File

@ -23,7 +23,10 @@
| See https://github.com/Kalmalyzer/kalms-c2p
.globl _asm_c2p1x1_8
.globl _asm_c2p1x1_8_tt
.globl _asm_c2p1x1_8_rect
.globl _asm_c2p1x1_4
.globl _asm_c2p1x1_4_rect
.text
@ -225,6 +228,221 @@ c2p1x1_8_start:
rts
| void asm_c2p1x1_8_tt(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen, uint32 screenPitch);
_asm_c2p1x1_8_tt:
movem.l d2-d7/a2-a6,-(sp) | 6 + 5 = 11 longs
move.l (11*4+4,sp),a0 | a0: chunky
move.l (11*4+8,sp),a2 | a2: chunky end
move.l (11*4+12,sp),a1 | a1: screen
move.l (11*4+16,sp),d0 | d0.l: screen pitch (double width)
move.l sp,old_sp
move.l d0,screen_pitch
lsr.l #1,d0
lea (a1,d0.l),a7 | a7: end of first dst line
move.l d0,screen_offset
move.l #0x0f0f0f0f,d4
move.l #0x00ff00ff,d5
move.l #0x55555555,d6
move.l (a0)+,d0
move.l (a0)+,d1
move.l (a0)+,d2
move.l (a0)+,d3
| a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
| e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
| i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0
| m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0
move.l d1,d7
lsr.l #4,d7
eor.l d0,d7
and.l d4,d7
eor.l d7,d0
lsl.l #4,d7
eor.l d7,d1
move.l d3,d7
lsr.l #4,d7
eor.l d2,d7
and.l d4,d7
eor.l d7,d2
lsl.l #4,d7
eor.l d7,d3
| a7a6a5a4e7e6e5e4 b7b6b5b4f7f6f5f4 c7c6c5c4g7g6g5g4 d7d6d5d4h7h6h5h4
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
| i7i6i5i4m7m6m5m4 j7j6j5j4n7n6n5n4 k7k6k5k4o7o6o5o4 l7l6l5l4p7p6p5p4
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
move.l d2,d7
lsr.l #8,d7
eor.l d0,d7
and.l d5,d7
eor.l d7,d0
lsl.l #8,d7
eor.l d7,d2
move.l d3,d7
lsr.l #8,d7
eor.l d1,d7
and.l d5,d7
eor.l d7,d1
lsl.l #8,d7
eor.l d7,d3
| a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
| b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
bra.s c2p1x1_8_tt_start
c2p1x1_8_tt_pix16:
move.l (a0)+,d0
move.l (a0)+,d1
move.l (a0)+,d2
move.l (a0)+,d3
| a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
| e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
| i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0
| m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0
move.l d1,d7
lsr.l #4,d7
move.l a3,(a1)+
eor.l d0,d7
and.l d4,d7
eor.l d7,d0
lsl.l #4,d7
eor.l d7,d1
move.l d3,d7
lsr.l #4,d7
eor.l d2,d7
and.l d4,d7
eor.l d7,d2
move.l a4,(a1)+
lsl.l #4,d7
eor.l d7,d3
| a7a6a5a4e7e6e5e4 b7b6b5b4f7f6f5f4 c7c6c5c4g7g6g5g4 d7d6d5d4h7h6h5h4
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
| i7i6i5i4m7m6m5m4 j7j6j5j4n7n6n5n4 k7k6k5k4o7o6o5o4 l7l6l5l4p7p6p5p4
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
move.l d2,d7
lsr.l #8,d7
eor.l d0,d7
and.l d5,d7
eor.l d7,d0
move.l a5,(a1)+
lsl.l #8,d7
eor.l d7,d2
move.l d3,d7
lsr.l #8,d7
eor.l d1,d7
and.l d5,d7
eor.l d7,d1
move.l a6,(a1)+
lsl.l #8,d7
eor.l d7,d3
| a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
| b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
cmp.l a1,a7 | end of dst line?
bne.s c2p1x1_8_tt_start
add.l (screen_offset,pc),a1
add.l (screen_pitch,pc),a7
c2p1x1_8_tt_start:
move.l d2,d7
lsr.l #1,d7
eor.l d0,d7
and.l d6,d7
eor.l d7,d0
add.l d7,d7
eor.l d7,d2
move.l d3,d7
lsr.l #1,d7
eor.l d1,d7
and.l d6,d7
eor.l d7,d1
add.l d7,d7
eor.l d7,d3
| a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1
| a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4
| a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
move.w d2,d7
move.w d0,d2
swap d2
move.w d2,d0
move.w d7,d2
move.w d3,d7
move.w d1,d3
swap d3
move.w d3,d1
move.w d7,d3
| a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0
| c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4
| c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
move.l d2,d7
lsr.l #2,d7
eor.l d0,d7
and.l #0x33333333,d7
eor.l d7,d0
lsl.l #2,d7
eor.l d7,d2
move.l d3,d7
lsr.l #2,d7
eor.l d1,d7
and.l #0x33333333,d7
eor.l d7,d1
lsl.l #2,d7
eor.l d7,d3
| a7b7c7d7e7f7g7h7 i7j7k7l7m7n7o7p7 a6b6c6d6e6f6g6h6 i6j6k6l6m6n6o6p6
| a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2
| a5b5c5d5e5f5g5h5 i5j5k5l5m5n5o5p5 a4b4c4d4e4f4g4h4 i4j4k4l4m4n4o4p4
| a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0
swap d0
swap d1
swap d2
swap d3
move.l d0,a6
move.l d2,a5
move.l d1,a4
move.l d3,a3
cmp.l a0,a2
bne c2p1x1_8_tt_pix16
move.l a3,(a1)+
move.l a4,(a1)+
move.l a5,(a1)+
move.l a6,(a1)+
move.l old_sp,sp
movem.l (sp)+,d2-d7/a2-a6
rts
| void asm_c2p1x1_8_rect(const byte *pChunky, const byte *pChunkyEnd, uint32 chunkyWidth, uint32 chunkyPitch, byte *pScreen, uint32 screenPitch);
_asm_c2p1x1_8_rect:
movem.l d2-d7/a2-a6,-(sp) | 6 + 5 = 11 longs
@ -456,6 +674,253 @@ c2p1x1_8_rect_done:
movem.l (sp)+,d2-d7/a2-a6
rts
| void asm_c2p1x1_4(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
_asm_c2p1x1_4:
move.l (4,sp),a0 | chunky
move.l (8,sp),d0 | chunky end
move.l (12,sp),a1 | screen
movem.l d2-d7/a2-a6,-(sp)
move.l d0,a2
move.l #0x0f0f0f0f,d4
move.l #0x00ff00ff,d5
move.l #0x55555555,d6
move.l (a0)+,d0
move.l (a0)+,d2
move.l (a0)+,d1
move.l (a0)+,d3
and.l d4,d0
and.l d4,d2
and.l d4,d1
and.l d4,d3
lsl.l #4,d0
lsl.l #4,d1
or.l d2,d0
or.l d3,d1
bra.s c2p1x1_4_start
c2p1x1_4_pix16:
move.l (a0)+,d0
move.l (a0)+,d2
move.l (a0)+,d1
move.l (a0)+,d3
and.l d4,d0
and.l d4,d2
move.l a5,(a1)+
and.l d4,d1
and.l d4,d3
move.l a6,(a1)+
lsl.l #4,d0
lsl.l #4,d1
or.l d2,d0
or.l d3,d1
c2p1x1_4_start:
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
move.l d1,d7
lsr.l #8,d7
eor.l d0,d7
and.l d5,d7
eor.l d7,d0
lsl.l #8,d7
eor.l d7,d1
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
move.l d1,d7
lsr.l #1,d7
eor.l d0,d7
and.l d6,d7
eor.l d7,d0
add.l d7,d7
eor.l d7,d1
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1
| a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
move.w d1,d7
move.w d0,d1
swap d1
move.w d1,d0
move.w d7,d1
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0
| c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
move.l d1,d7
lsr.l #2,d7
eor.l d0,d7
and.l #0x33333333,d7
eor.l d7,d0
lsl.l #2,d7
eor.l d7,d1
| a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2
| a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0
swap d0
swap d1
move.l d1,a5
move.l d0,a6
cmp.l a0,a2
bne.s c2p1x1_4_pix16
move.l a5,(a1)+
move.l a6,(a1)+
movem.l (sp)+,d2-d7/a2-a6
rts
| void asm_c2p1x1_4_rect(const byte *pChunky, const byte *pChunkyEnd, uint32 chunkyWidth, uint32 chunkyPitch, byte *pScreen, uint32 screenPitch);
_asm_c2p1x1_4_rect:
movem.l d2-d7/a2-a6,-(sp) | 6 + 5 = 11 longs
move.l (11*4+4,sp),a0 | a0: chunky
move.l (11*4+8,sp),chunky_end
move.l (11*4+12,sp),d0 | d0.l: chunky width
move.l (11*4+16,sp),d2 | d2.l: chunky pitch
move.l (11*4+20,sp),a1 | a1: screen
move.l (11*4+24,sp),d1 | d1.l: screen pitch
move.l sp,old_sp
move.l d0,d3 | d3.l: screen width
lsr.l #1,d3 |
lea (a0,d0.l),a2 | a2: end of first src line
lea (a1,d3.l),a7 | a7: end of first dst line
move.l d1,screen_pitch
sub.l d3,d1
move.l d1,screen_offset
move.l d2,chunky_pitch
sub.l d0,d2
move.l d2,chunky_offset
move.l #0x0f0f0f0f,d4
move.l #0x00ff00ff,d5
move.l #0x55555555,d6
move.l (a0)+,d0
move.l (a0)+,d2
move.l (a0)+,d1
move.l (a0)+,d3
and.l d4,d0
and.l d4,d2
and.l d4,d1
and.l d4,d3
lsl.l #4,d0
lsl.l #4,d1
or.l d2,d0
or.l d3,d1
bra.s c2p1x1_4_rect_start
c2p1x1_4_rect_pix16:
move.l (a0)+,d0
move.l (a0)+,d2
move.l (a0)+,d1
move.l (a0)+,d3
and.l d4,d0
and.l d4,d2
move.l a5,(a1)+
and.l d4,d1
and.l d4,d3
move.l a6,(a1)+
lsl.l #4,d0
lsl.l #4,d1
or.l d2,d0
or.l d3,d1
cmp.l a1,a7 | end of dst line?
bne.s c2p1x1_4_rect_start
add.l (screen_offset,pc),a1
add.l (screen_pitch,pc),a7
c2p1x1_4_rect_start:
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
move.l d1,d7
lsr.l #8,d7
eor.l d0,d7
and.l d5,d7
eor.l d7,d0
lsl.l #8,d7
eor.l d7,d1
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
move.l d1,d7
lsr.l #1,d7
eor.l d0,d7
and.l d6,d7
eor.l d7,d0
add.l d7,d7
eor.l d7,d1
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1
| a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
move.w d1,d7
move.w d0,d1
swap d1
move.w d1,d0
move.w d7,d1
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0
| c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
move.l d1,d7
lsr.l #2,d7
eor.l d0,d7
and.l #0x33333333,d7
eor.l d7,d0
lsl.l #2,d7
eor.l d7,d1
| a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2
| a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0
swap d0
swap d1
move.l d1,a5
move.l d0,a6
cmp.l a0,a2 | end of src line?
bne c2p1x1_4_rect_pix16
cmp.l (chunky_end,pc),a2
beq.s c2p1x1_4_rect_done
add.l (chunky_offset,pc),a0
add.l (chunky_pitch,pc),a2
bra c2p1x1_4_rect_pix16
c2p1x1_4_rect_done:
move.l a5,(a1)+
move.l a6,(a1)+
move.l old_sp,sp
movem.l (sp)+,d2-d7/a2-a6
rts
| place it within reach of 32K (PC relative)
screen_pitch:
ds.l 1

View File

@ -31,11 +31,22 @@ extern "C" {
* Optimized for surface-to-surface copy with the same pitch.
*
* @param pChunky chunky buffer start
* @param pChunkyEnd chunky buffer end (including the last byte)
* @param pChunkyEnd chunky buffer end (past-the-end iterator)
* @param pScreen bitplane screen start
*/
void asm_c2p1x1_8(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
/**
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into eight bitplanes.
* Optimized for surface-to-surface copy with the double screen pitch (typically 320x480).
*
* @param pChunky chunky buffer start
* @param pChunkyEnd chunky buffer end (past-the-end iterator)
* @param pScreen bitplane screen start
* @param screenPitch bitplane screen width (in bytes)
*/
void asm_c2p1x1_8_tt(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen, uint32 screenPitch);
/**
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into eight bitplanes.
* Optimized for arbitrary rectangle position and dimension (16px aligned).
@ -49,6 +60,29 @@ void asm_c2p1x1_8(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
*/
void asm_c2p1x1_8_rect(const byte *pChunky, const byte *pChunkyEnd, uint32 chunkyWidth, uint32 chunkyPitch, byte *pScreen, uint32 screenPitch);
/**
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into four bitplanes.
* Optimized for surface-to-surface copy with the same pitch.
*
* @param pChunky chunky buffer start
* @param pChunkyEnd chunky buffer end (past-the-end iterator)
* @param pScreen bitplane screen start
*/
void asm_c2p1x1_4(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
/**
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into four bitplanes.
* Optimized for arbitrary rectangle position and dimension (16px aligned).
*
* @param pChunky chunky buffer at rectangle's [X1, Y1] position
* @param pChunkyEnd chunky buffer at rectangle's [X2, Y2] position (included)
* @param chunkyWidth rectangle width
* @param chunkyPitch chunky buffer width (in bytes)
* @param pScreen bitplane screen at rectangle's [X1, Y1] position
* @param screenPitch bitplane screen width (in bytes)
*/
void asm_c2p1x1_4_rect(const byte *pChunky, const byte *pChunkyEnd, uint32 chunkyWidth, uint32 chunkyPitch, byte *pScreen, uint32 screenPitch);
}
#endif

View File

@ -1,194 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "backends/graphics/atari/videl-resolutions.h"
#include "common/scummsys.h"
const byte scp_320x200x8_rgb[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x48, 0x7a, 0xb0, 0x00, 0xa9, 0xc1, 0x08, 0x00, 0xc2, 0x8c, 0xb0,
0x01, 0x64, 0x05, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x3d, 0x09, 0x00, 0x00,
0x00, 0xc0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x40,
0x00, 0xc8, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0x00, 0x99, 0x00, 0x59, 0x00, 0x26, 0x00, 0x87,
0x00, 0xd9, 0x02, 0x71, 0x02, 0x11, 0x00, 0x81, 0x00, 0x81, 0x02, 0x11,
0x02, 0x6b, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0xa0
};
const byte scp_320x200x8_rgb60[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x48, 0x7a, 0xb0, 0x00, 0xa7, 0xd8, 0xc0, 0x00, 0xc4, 0x74, 0xf8,
0x01, 0x60, 0x05, 0x00, 0x02, 0x54, 0x00, 0x00, 0x3d, 0x09, 0x00, 0x00,
0x00, 0xc0, 0x00, 0x00, 0x08, 0xc0, 0x00, 0x00, 0x06, 0xc0, 0x00, 0x23,
0x00, 0xc8, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0x00, 0x98, 0x00, 0x58, 0x00, 0x25, 0x00, 0x86,
0x00, 0xd9, 0x02, 0x0d, 0x01, 0xd7, 0x00, 0x47, 0x00, 0x47, 0x01, 0xd7,
0x02, 0x07, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0xa0
};
byte scp_320x200x8_vga[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3a, 0x2f, 0x00, 0x00, 0x19, 0x74, 0x90, 0x00, 0x46, 0x4e, 0x20,
0x00, 0x2a, 0x02, 0x80, 0x02, 0x58, 0x00, 0x00, 0x7a, 0xee, 0x00, 0x00,
0x00, 0x3e, 0x00, 0x00, 0x08, 0x7a, 0x00, 0x00, 0x06, 0x8a, 0x00, 0x46,
0x01, 0x90, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xc6, 0x00, 0x8d, 0x00, 0x15, 0x02, 0x9a, 0x00, 0x7b,
0x00, 0x97, 0x04, 0x19, 0x03, 0xad, 0x00, 0x8d, 0x00, 0x8d, 0x03, 0xad,
0x04, 0x15, 0x02, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x10, 0x00, 0x05,
0x00, 0xa0
};
const byte scp_320x240x8_rgb[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x33, 0x32, 0x30, 0x2a,
0x32, 0x30, 0x30, 0x2c, 0x20, 0x32, 0x35, 0x36, 0x20, 0x46, 0x61, 0x72,
0x62, 0x65, 0x6e, 0x2c, 0x20, 0x35, 0x30, 0x2e, 0x30, 0x20, 0x48, 0x7a,
0x2c, 0x20, 0x31, 0x35, 0x36, 0x32, 0x35, 0x20, 0x48, 0x7a, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x48, 0x7a, 0xb0, 0x00, 0xa9, 0xc1, 0x08, 0x00, 0xc2, 0x8c, 0xb0,
0x01, 0x64, 0x05, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x3d, 0x09, 0x00, 0x00,
0x00, 0xc0, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x2c,
0x00, 0xf0, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0x00, 0x99, 0x00, 0x59, 0x00, 0x26, 0x00, 0x87,
0x00, 0xd9, 0x02, 0x71, 0x02, 0x39, 0x00, 0x59, 0x00, 0x59, 0x02, 0x39,
0x02, 0x6b, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0xa0
};
byte scp_320x240x8_vga[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3a, 0x2f, 0x00, 0x00, 0x19, 0x74, 0x90, 0x00, 0x46, 0x4e, 0x20,
0x00, 0x2a, 0x02, 0x80, 0x02, 0x58, 0x00, 0x00, 0x7a, 0xee, 0x00, 0x00,
0x00, 0x3e, 0x00, 0x00, 0x03, 0xc1, 0x00, 0x00, 0x01, 0x93, 0x00, 0x1f,
0x01, 0xe0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xc6, 0x00, 0x8d, 0x00, 0x15, 0x02, 0x9a, 0x00, 0x7b,
0x00, 0x97, 0x04, 0x19, 0x03, 0xff, 0x00, 0x3f, 0x00, 0x3f, 0x03, 0xff,
0x04, 0x15, 0x02, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x10, 0x00, 0x05,
0x00, 0xa0
};
const byte scp_640x400x8_rgb[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x48, 0x7a, 0xb0, 0x00, 0xab, 0xa9, 0x50, 0x00, 0xc1, 0x98, 0x8c,
0x01, 0x68, 0x05, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x3d, 0x09, 0x00, 0x00,
0x00, 0xc0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x40,
0x00, 0xc8, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xfe, 0x01, 0x34, 0x00, 0xb4, 0x00, 0x71, 0x01, 0x22,
0x01, 0xb3, 0x02, 0x70, 0x02, 0x11, 0x00, 0x81, 0x00, 0x80, 0x02, 0x10,
0x02, 0x6b, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06,
0x01, 0x40
};
const byte scp_640x400x8_rgb60[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x47, 0x86, 0x8c, 0x00, 0xb1, 0x62, 0x28, 0x00, 0xbd, 0xc7, 0xfc,
0x01, 0x74, 0x05, 0x00, 0x02, 0x53, 0x00, 0x00, 0x3c, 0xea, 0x00, 0x00,
0x00, 0xc0, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x06, 0x40, 0x00, 0x25,
0x00, 0xc8, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xff, 0x01, 0x39, 0x00, 0xba, 0x00, 0x77, 0x01, 0x27,
0x01, 0xb5, 0x02, 0x0c, 0x01, 0xdb, 0x00, 0x4b, 0x00, 0x4a, 0x01, 0xda,
0x02, 0x07, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06,
0x01, 0x40
};
byte scp_640x400x8_vga[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x02, 0x36, 0x34, 0x30, 0x2a,
0x34, 0x38, 0x30, 0x2c, 0x20, 0x32, 0x35, 0x36, 0x20, 0x46, 0x61, 0x72,
0x62, 0x65, 0x6e, 0x2c, 0x20, 0x36, 0x30, 0x2e, 0x30, 0x20, 0x48, 0x7a,
0x2c, 0x20, 0x33, 0x31, 0x34, 0x37, 0x30, 0x20, 0x48, 0x7a, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3a, 0x2f, 0x00, 0x00, 0x1a, 0xaa, 0xe0, 0x00, 0x45, 0x17, 0xd0,
0x00, 0x2c, 0x02, 0x80, 0x02, 0x58, 0x00, 0x00, 0x7a, 0xee, 0x00, 0x00,
0x00, 0x3e, 0x00, 0x00, 0x08, 0x99, 0x00, 0x00, 0x06, 0x6b, 0x00, 0x47,
0x01, 0x90, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xc6, 0x00, 0x8e, 0x00, 0x16, 0x02, 0xac, 0x00, 0x85,
0x00, 0x97, 0x04, 0x19, 0x03, 0xaf, 0x00, 0x8f, 0x00, 0x8f, 0x03, 0xaf,
0x04, 0x15, 0x02, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08,
0x01, 0x40
};
const byte scp_640x480x8_rgb[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x36, 0x34, 0x30, 0x2a,
0x34, 0x30, 0x30, 0x2c, 0x20, 0x32, 0x35, 0x36, 0x20, 0x46, 0x61, 0x72,
0x62, 0x65, 0x6e, 0x2c, 0x20, 0x35, 0x30, 0x2e, 0x30, 0x20, 0x48, 0x7a,
0x20, 0x28, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x2e, 0x29, 0x2c, 0x20,
0x31, 0x35, 0x36, 0x32, 0x35, 0x20, 0x48, 0x7a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x48, 0x7a, 0xb0, 0x00, 0xab, 0xa9, 0x50, 0x00, 0xc1, 0x98, 0x8c,
0x01, 0x68, 0x05, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x3d, 0x09, 0x00, 0x00,
0x00, 0xc0, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x07, 0x40, 0x00, 0x2b,
0x00, 0xf0, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xfe, 0x01, 0x34, 0x00, 0xb4, 0x00, 0x71, 0x01, 0x22,
0x01, 0xb3, 0x02, 0x70, 0x02, 0x37, 0x00, 0x57, 0x00, 0x56, 0x02, 0x36,
0x02, 0x6b, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06,
0x01, 0x40
};
byte scp_640x480x8_vga[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3a, 0x2f, 0x00, 0x00, 0x1a, 0xaa, 0xe0, 0x00, 0x45, 0x17, 0xd0,
0x00, 0x2c, 0x02, 0x80, 0x02, 0x58, 0x00, 0x00, 0x7a, 0xee, 0x00, 0x00,
0x00, 0x3e, 0x00, 0x00, 0x03, 0xc1, 0x00, 0x00, 0x01, 0x93, 0x00, 0x1f,
0x01, 0xe0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01, 0xe8, 0x48, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xc6, 0x00, 0x8e, 0x00, 0x16, 0x02, 0xac, 0x00, 0x85,
0x00, 0x97, 0x04, 0x19, 0x03, 0xff, 0x00, 0x3f, 0x00, 0x3f, 0x03, 0xff,
0x04, 0x15, 0x02, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08,
0x01, 0x40
};

View File

@ -1,43 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef BACKENDS_GRAPHICS_ATARI_VIDEL_RESOLUTIONS_H
#define BACKENDS_GRAPHICS_ATARI_VIDEL_RESOLUTIONS_H
#include "common/scummsys.h"
constexpr int SCP_SIZE = 158;
extern const byte scp_320x200x8_rgb[SCP_SIZE];
extern const byte scp_320x200x8_rgb60[SCP_SIZE];
extern byte scp_320x200x8_vga[SCP_SIZE];
extern const byte scp_320x240x8_rgb[SCP_SIZE];
extern byte scp_320x240x8_vga[SCP_SIZE];
extern const byte scp_640x400x8_rgb[SCP_SIZE];
extern const byte scp_640x400x8_rgb60[SCP_SIZE];
extern byte scp_640x400x8_vga[SCP_SIZE];
extern const byte scp_640x480x8_rgb[SCP_SIZE];
extern byte scp_640x480x8_vga[SCP_SIZE];
#endif

View File

@ -22,126 +22,197 @@
#include "backends/mixer/atari/atari-mixer.h"
#include <math.h>
#include <mint/cookie.h>
#include <mint/falcon.h>
#include <mint/osbind.h>
#include <mint/ostruct.h>
#include "common/config-manager.h"
#include "common/debug.h"
#define DEFAULT_OUTPUT_RATE 24585
static bool s_audioNotAvailable = true;
void AtariAudioShutdown() {
if (!s_audioNotAvailable) {
Buffoper(0x00);
Sndstatus(SND_RESET);
Unlocksnd();
}
}
AtariMixerManager::AtariMixerManager() : MixerManager() {
debug("AtariMixerManager()");
_audioSuspended = true;
ConfMan.registerDefault("output_rate", DEFAULT_OUTPUT_RATE);
_outputRate = ConfMan.getInt("output_rate");
if (_outputRate <= 0)
_outputRate = DEFAULT_OUTPUT_RATE;
int diff50, diff33, diff25, diff20, diff16, diff12, diff10, diff8;
diff50 = abs(49170 - (int)_outputRate);
diff33 = abs(32780 - (int)_outputRate);
diff25 = abs(24585 - (int)_outputRate);
diff20 = abs(19668 - (int)_outputRate);
diff16 = abs(16390 - (int)_outputRate);
diff12 = abs(12292 - (int)_outputRate);
diff10 = abs(9834 - (int)_outputRate);
diff8 = abs(8195 - (int)_outputRate);
if (diff50 < diff33) {
_outputRate = 49170;
_clk = CLK50K;
} else if (diff33 < diff25) {
_outputRate = 32780;
_clk = CLK33K;
} else if (diff25 < diff20) {
_outputRate = 24585;
_clk = CLK25K;
} else if (diff20 < diff16) {
_outputRate = 19668;
_clk = CLK20K;
} else if (diff16 < diff12) {
_outputRate = 16390;
_clk = CLK16K;
} else if (diff12 < diff10) {
_outputRate = 12292;
_clk = CLK12K;
} else if (diff10 < diff8) {
_outputRate = 9834;
_clk = CLK10K;
} else {
_outputRate = 8195;
_clk = CLK8K;
}
ConfMan.setInt("output_rate", _outputRate);
debug("setting %d Hz mixing frequency", _outputRate);
_samples = 8192;
while (_samples * 16 > _outputRate * 2)
_samples >>= 1;
ConfMan.registerDefault("audio_buffer_size", (int)_samples);
int samples = ConfMan.getInt("audio_buffer_size");
if (samples > 0)
_samples = samples;
ConfMan.setInt("audio_buffer_size", (int)_samples);
debug("sample buffer size: %d", _samples);
ConfMan.flushToDisk();
_samplesBuf = new uint8[_samples * 4];
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
}
AtariMixerManager::~AtariMixerManager() {
debug("~AtariMixerManager()");
g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
Buffoper(0x00);
if (s_audioNotAvailable)
return;
AtariAudioShutdown();
Mfree(_atariSampleBuffer);
_atariSampleBuffer = _atariPhysicalSampleBuffer = _atariLogicalSampleBuffer = nullptr;
Sndstatus(SND_RESET);
Unlocksnd();
_atariInitialized = false;
delete[] _samplesBuf;
}
void AtariMixerManager::init() {
long cookie;
bool useDevconnectReturnValue = false;
if (Getcookie(C__SND, &cookie) == C_FOUND) {
if (cookie & SND_16BIT)
s_audioNotAvailable = false;
useDevconnectReturnValue = (cookie & SND_EXT) != 0;
}
if (s_audioNotAvailable) {
warning("Mixer manager requires 16-bit stereo mode, disabling");
} else {
int clk;
if (Locksnd() < 0)
error("Sound system is locked");
// try XBIOS APIs which do not set SND_EXT in _SND
useDevconnectReturnValue |= (Getcookie(C_STFA, &cookie) == C_FOUND); // STFA
useDevconnectReturnValue |= (Getcookie(C_McSn, &cookie) == C_FOUND); // X-SOUND, MacSound
// reset connection matrix (and other settings)
Sndstatus(SND_RESET);
int diff50, diff33, diff25, diff20, diff16, diff12, diff10, diff8, diff6;
diff50 = abs(49170 - (int)_outputRate);
diff33 = abs(32780 - (int)_outputRate);
diff25 = abs(24585 - (int)_outputRate);
diff20 = abs(19668 - (int)_outputRate);
diff16 = abs(16390 - (int)_outputRate);
diff12 = abs(12292 - (int)_outputRate);
diff10 = abs(9834 - (int)_outputRate);
diff8 = abs(8195 - (int)_outputRate);
if (diff50 < diff33) {
_outputRate = 49170;
clk = CLK50K;
} else if (diff33 < diff25) {
_outputRate = 32780;
clk = CLK33K;
} else if (diff25 < diff20) {
_outputRate = 24585;
clk = CLK25K;
} else if (diff20 < diff16) {
_outputRate = 19668;
clk = CLK20K;
} else if (diff16 < diff12) {
_outputRate = 16390;
clk = CLK16K;
} else if (diff12 < diff10) {
_outputRate = 12292;
clk = CLK12K;
} else if (diff10 < diff8) {
_outputRate = 9834;
clk = CLK10K;
} else {
_outputRate = 8195;
clk = CLK8K;
}
// first try to use Devconnect() with a Falcon prescaler
if (Devconnect(DMAPLAY, DAC, CLK25M, clk, NO_SHAKE) != 0) {
// the return value is broken on Falcon
if (useDevconnectReturnValue) {
if (Devconnect(DMAPLAY, DAC, CLK25M, CLKOLD, NO_SHAKE) == 0) {
// calculate compatible prescaler
diff50 = abs(50066 - (int)_outputRate);
diff25 = abs(25033 - (int)_outputRate);
diff12 = abs(12517 - (int)_outputRate);
diff6 = abs(6258 - (int)_outputRate);
if (diff50 < diff25) {
_outputRate = 50066;
clk = PRE160;
} else if (diff25 < diff12) {
_outputRate = 25033;
clk = PRE320;
} else if (diff12 < diff6) {
_outputRate = 12517;
clk = PRE640;
} else {
_outputRate = 6258;
clk = PRE1280;
}
Soundcmd(SETPRESCALE, clk);
} else {
error("Devconnect() failed");
}
}
}
ConfMan.setInt("output_rate", _outputRate);
debug("setting %d Hz mixing frequency", _outputRate);
_samples = 8192;
while (_samples * 16 > _outputRate * 2)
_samples >>= 1;
ConfMan.registerDefault("audio_buffer_size", (int)_samples);
int samples = ConfMan.getInt("audio_buffer_size");
if (samples > 0)
_samples = samples;
ConfMan.setInt("audio_buffer_size", (int)_samples);
debug("sample buffer size: %d", _samples);
ConfMan.flushToDisk();
_atariSampleBufferSize = _samples * 4;
_atariSampleBuffer = (byte*)Mxalloc(_atariSampleBufferSize * 2, MX_STRAM);
if (!_atariSampleBuffer)
error("Failed to allocate memory in ST RAM");
_atariPhysicalSampleBuffer = _atariSampleBuffer;
_atariLogicalSampleBuffer = _atariSampleBuffer + _atariSampleBufferSize;
memset(_atariSampleBuffer, 0, 2 * _atariSampleBufferSize);
Setmode(MODE_STEREO16);
Soundcmd(ADDERIN, MATIN);
Setbuffer(SR_PLAY, _atariSampleBuffer, _atariSampleBuffer + 2 * _atariSampleBufferSize);
Buffoper(SB_PLA_ENA | SB_PLA_RPT);
_samplesBuf = new uint8[_samples * 4];
}
_mixer = new Audio::MixerImpl(_outputRate, _samples);
_mixer->setReady(true);
_atariSampleBufferSize = _samples * 4;
_atariSampleBuffer = (byte*)Mxalloc(_atariSampleBufferSize * 2, MX_STRAM);
if (!_atariSampleBuffer)
return;
_atariPhysicalSampleBuffer = _atariSampleBuffer;
_atariLogicalSampleBuffer = _atariSampleBuffer + _atariSampleBufferSize;
memset(_atariSampleBuffer, 0, 2 * _atariSampleBufferSize);
if (Locksnd() < 0)
return;
Sndstatus(SND_RESET);
Setmode(MODE_STEREO16);
Devconnect(DMAPLAY, DAC, CLK25M, _clk, NO_SHAKE);
Soundcmd(ADDERIN, MATIN);
Setbuffer(SR_PLAY, _atariSampleBuffer, _atariSampleBuffer + 2 * _atariSampleBufferSize);
Buffoper(SB_PLA_ENA | SB_PLA_RPT);
_atariInitialized = true;
_audioSuspended = false;
}
void AtariMixerManager::suspendAudio() {
if (s_audioNotAvailable)
return;
debug("suspendAudio");
Buffoper(0x00);
@ -150,13 +221,10 @@ void AtariMixerManager::suspendAudio() {
}
int AtariMixerManager::resumeAudio() {
debug("resumeAudio 1");
if (s_audioNotAvailable)
return 0;
if (!_audioSuspended || !_atariInitialized) {
return -2;
}
debug("resumeAudio 2");
debug("resumeAudio");
Buffoper(SB_PLA_ENA | SB_PLA_RPT);
@ -165,10 +233,13 @@ int AtariMixerManager::resumeAudio() {
}
bool AtariMixerManager::notifyEvent(const Common::Event &event) {
if (s_audioNotAvailable)
return false;
switch (event.type) {
case Common::EVENT_QUIT:
case Common::EVENT_RETURN_TO_LAUNCHER:
debug("silencing the mixer");
debug("silencing the mixer"); // TODO: is it for long enough?
memset(_atariSampleBuffer, 0, 2 * _atariSampleBufferSize);
return false;
case Common::EVENT_MUTE:
@ -187,6 +258,12 @@ void AtariMixerManager::update() {
return;
}
if (s_audioNotAvailable) {
static byte dummy[4];
_mixer->mixCallback(dummy, 0);
return;
}
static bool loadSampleFlag = true;
byte *buf = nullptr;
@ -195,20 +272,18 @@ void AtariMixerManager::update() {
return;
if (!loadSampleFlag) {
// we play from _atariPhysicalSampleBuffer (1st buffer)
if ((byte*)sPtr.play < _atariLogicalSampleBuffer) {
buf = _atariLogicalSampleBuffer;
loadSampleFlag = !loadSampleFlag;
}
} else {
// we play from _atariLogicalSampleBuffer (2nd buffer)
if ((byte*)sPtr.play >= _atariLogicalSampleBuffer) {
buf = _atariPhysicalSampleBuffer;
loadSampleFlag = !loadSampleFlag;
}
}
if (_atariInitialized && buf != nullptr) {
if (buf != nullptr) {
assert(_mixer);
// generates stereo 16-bit samples
int processed = _mixer->mixCallback(_samplesBuf, _muted ? 0 : _samples * 4);

View File

@ -43,12 +43,10 @@ public:
bool notifyEvent(const Common::Event &event) override;
private:
int _clk;
uint32 _outputRate;
uint32 _samples;
uint8 *_samplesBuf;
uint32 _samples = 0;
uint8 *_samplesBuf = nullptr;
bool _atariInitialized = false;
byte *_atariSampleBuffer = nullptr;
byte *_atariPhysicalSampleBuffer = nullptr;
byte *_atariLogicalSampleBuffer = nullptr;

View File

@ -360,7 +360,6 @@ MODULE_OBJS += \
graphics/atari/atari_c2p-asm.o \
graphics/atari/atari-graphics.o \
graphics/atari/atari-graphics-asm.o \
graphics/atari/videl-resolutions.o \
mixer/atari/atari-mixer.o
endif

View File

@ -19,215 +19,58 @@
*
*/
/*
* IKBD 6301 interrupt routine
*
* Patrice Mandin
*/
.global _atari_kbdvec
.global _atari_mousevec
.global _atari_vkbderr
.globl _atari_ikbd_init
.globl _atari_ikbd_shutdown
.globl _g_atari_ikbd_mouse_buttons_state
.globl _g_atari_ikbd_mouse_delta_x
.globl _g_atari_ikbd_mouse_delta_y
.globl _g_atari_ikbd_scancodes
.globl _g_atari_ikbd_scancodes_size
.globl _g_atari_ikbb_scancodes_head
.extern _g_atari_ikbd_mouse_buttons_state
.extern _g_atari_ikbd_mouse_delta_x
.extern _g_atari_ikbd_mouse_delta_y
.extern _g_atari_ikbd_scancodes
.extern _g_atari_ikbd_scancodes_mask
.extern _g_atari_ikbb_scancodes_head
.text
_atari_ikbd_init:
| Disable interrupts
_atari_kbdvec:
tst.w (vkbderr_count,pc)
bne.b kbdvec_end
movew sr,d1
movew #0x2700,sr
| Save MFP registers used for keyboard
lea 0xfffffa00:w,a0
btst #6,a0@(0x09)
sne ikbd_ierb
btst #6,a0@(0x15)
sne ikbd_imrb
| Set our routine
movel 0x118:w,old_ikbd
movel #ikbd,0x118:w
bset #6,0xfffffa09:w | IERB
bset #6,0xfffffa15:w | IMRB
| Set mouse relative mode
moveb #8,0xfffffc02:w
| Reenable interrupts
movew d1,sr
rts
_atari_ikbd_shutdown:
| Disable interrupts
movew sr,d1
movew #0x2700,sr
| Restore previous MFP registers
lea 0xfffffa00:w,a0
bclr #6,a0@(0x09)
tstb ikbd_ierb
beqs ikbd_restoreierb
bset #6,a0@(0x09)
ikbd_restoreierb:
bclr #6,a0@(0x15)
tstb ikbd_imrb
beqs ikbd_restoreimrb
bset #6,a0@(0x15)
ikbd_restoreimrb:
movel old_ikbd,0x118:w
| Clear keyboard buffer
lea 0xfffffc00:w,a0
ikbd_videbuffer:
btst #0,a0@
beqs ikbd_finbuffer
tstb a0@(0x02)
bras ikbd_videbuffer
ikbd_finbuffer:
| Reenable interrupts
movew d1,sr
rts
.bss
.even
ikbd_ierb:
.ds.b 1
ikbd_imrb:
.ds.b 1
/*--- Our custom IKBD vector ---*/
.text
.even
.ascii "XBRA"
.ascii "SCUM"
old_ikbd:
.dc.l 0
ikbd:
moveml d0-d1/a0,sp@-
| Check if source is IKBD or MIDI
btst #0,0xfffffc00.w
beqs ikbd_oldmidi
moveb 0xfffffc02:w,d0
| Not supported packets ?
| status report
cmpb #0xf6,d0
beqs ikbd_endit_stack
| absolute mouse position record
cmpb #0xf7,d0
beqs ikbd_endit_stack
| time-of-day
cmpb #0xfc,d0
beqs ikbd_endit_stack
| Joystick packet ?
| joystick report (both sticks), joystick 0 event, joystick 1 event
cmpb #0xfd,d0
bhss ikbd_endit_stack
| Mouse packet ?
cmpb #0xf8,d0
blos ikbd_no_mouse
cmpb #0xfc,d0
bhss ikbd_no_mouse
| Mouse packet, byte #1
ikbd_yes_mouse:
andw #3,d0
moveb d0,_g_atari_ikbd_mouse_buttons_state
movel #ikbd_mousex,0x118:w
bras ikbd_endit_stack
| Keyboard press/release
ikbd_no_mouse:
lea _g_atari_ikbd_scancodes,a0
movew _g_atari_ikbb_scancodes_head,d1
move.w _g_atari_ikbb_scancodes_head,d1
| g_atari_ikbd_scancodes[g_atari_ikbb_scancodes_head] = scancode
moveb d0,(0.b,a0,d1.w)
move.b d0,(0.b,a0,d1.w)
addql #1,d1
andw _g_atari_ikbd_scancodes_mask,d1
movew d1,_g_atari_ikbb_scancodes_head
addq.l #1,d1
and.w _g_atari_ikbd_scancodes_mask,d1
move.w d1,_g_atari_ikbb_scancodes_head
| End of interrupt
ikbd_endit_stack:
moveml sp@+,d0-d1/a0
bclr #6,0xfffffa11:w
rte
| Call old MIDI interrupt
ikbd_oldmidi:
moveml sp@+,d0-d1/a0
movel old_ikbd,sp@-
kbdvec_end:
rts
| Mouse packet, byte #2
ikbd_mousex:
moveml d0-d1/a0,sp@-
_atari_vkbderr:
addq.w #1,vkbderr_count
rts
| Check if source is IKBD or MIDI
btst #0,0xfffffc00.w
beqs ikbd_oldmidi
moveb 0xfffffc02:w,d0
extw d0
addw d0,_g_atari_ikbd_mouse_delta_x
_atari_mousevec:
clr.w vkbderr_count
movel #ikbd_mousey,0x118:w
bras ikbd_endit_stack
move.b (a0)+,_g_atari_ikbd_mouse_buttons_state
| Mouse packet, byte #3
move.b (a0)+,d0
ext.w d0
add.w d0,_g_atari_ikbd_mouse_delta_x
ikbd_mousey:
moveml d0-d1/a0,sp@-
move.b (a0)+,d0
ext.w d0
add.w d0,_g_atari_ikbd_mouse_delta_y
rts
| Check if source is IKBD or MIDI
btst #0,0xfffffc00.w
beqs ikbd_oldmidi
moveb 0xfffffc02:w,d0
extw d0
addw d0,_g_atari_ikbd_mouse_delta_y
movel #ikbd,0x118:w
bras ikbd_endit_stack
// place it within reach of 32K (PC relative)
vkbderr_count:
dc.w 0

View File

@ -43,7 +43,10 @@ do
unzip -d tmp "$f" && cd tmp && zip -0 ../$(basename "$f") * && cd .. && rm -r tmp && rm "$f"
done
)
# absent gui-icons.dat massively speeds up startup time (used for the grid mode)
rm ../data/gui-icons.dat
cd -
# readme.txt
cp ../backends/platform/atari/readme.txt dist-generic/scummvm
unix2dos dist-generic/scummvm/readme.txt

View File

@ -28,7 +28,8 @@ then
--disable-bink \
--opengl-mode=none \
--enable-verbose-build \
--enable-text-console
--enable-text-console \
--disable-engine=hugo
fi
make -j 16
@ -36,7 +37,8 @@ rm -rf dist-generic
make dist-generic
# remove themes
rm -f dist-generic/scummvm/data/*.zip
rm -f dist-generic/scummvm/data/*.zip dist-generic/scummvm/data/gui-icons.dat
# readme.txt
cp ../backends/platform/atari/readme.txt dist-generic/scummvm
unix2dos dist-generic/scummvm/readme.txt

View File

@ -22,34 +22,38 @@
#include <stdio.h>
#include <time.h>
#include <gem.h>
#include <mint/cookie.h>
#include <mint/falcon.h>
#include <mint/osbind.h>
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
#define FORBIDDEN_SYMBOL_EXCEPTION_stdout
#define FORBIDDEN_SYMBOL_EXCEPTION_stderr
#define FORBIDDEN_SYMBOL_EXCEPTION_fputs
#define FORBIDDEN_SYMBOL_EXCEPTION_exit
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
#define FORBIDDEN_SYMBOL_EXCEPTION_sprintf
#define FORBIDDEN_SYMBOL_EXCEPTION_stderr
#define FORBIDDEN_SYMBOL_EXCEPTION_stdout
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
#include "backends/platform/atari/osystem_atari.h"
#if defined(ATARI)
#include "backends/graphics/atari/atari-graphics-asm.h"
#include "backends/keymapper/hardware-input.h"
#include "backends/mutex/null/null-mutex.h"
#include "base/main.h"
#include "backends/saves/default/default-saves.h"
#include "backends/timer/default/default-timer.h"
#include "backends/audiocd/default/default-audiocd.h"
#include "common/config-manager.h"
#include "backends/events/atari/atari-events.h"
#include "backends/events/default/default-events.h"
#include "backends/mixer/atari/atari-mixer.h"
#include "backends/graphics/atari/atari-graphics.h"
#include "backends/graphics/atari/atari-graphics-asm.h"
#include "backends/graphics/atari/atari-graphics-superblitter.h"
#include "backends/graphics/atari/atari-graphics-supervidel.h"
#include "backends/graphics/atari/atari-graphics-videl.h"
#include "backends/graphics/atari/atari-graphics.h"
#include "backends/keymapper/hardware-input.h"
#include "backends/mixer/atari/atari-mixer.h"
#include "backends/mutex/null/null-mutex.h"
#include "backends/saves/default/default-saves.h"
#include "backends/timer/default/default-timer.h"
#include "base/main.h"
#include "gui/debugger.h"
/*
@ -57,8 +61,9 @@
*/
#include "backends/fs/posix/posix-fs-factory.h"
extern "C" void atari_ikbd_init();
extern "C" void atari_ikbd_shutdown();
extern "C" void atari_kbdvec(void *);
extern "C" void atari_mousevec(void *);
extern "C" void atari_vkbderr(void);
extern "C" void atari_200hz_init();
extern "C" void atari_200hz_shutdown();
@ -67,36 +72,79 @@ extern "C" volatile uint32 counter_200hz;
extern void nf_init(void);
extern void nf_print(const char* msg);
OSystem_Atari::OSystem_Atari() {
_fsFactory = new POSIXFilesystemFactory();
}
static int s_app_id = -1;
static int16 s_vdi_handle;
static int s_vdi_width, s_vdi_height;
OSystem_Atari::~OSystem_Atari() {
debug("OSystem_Atari::~OSystem_Atari()");
static bool s_tt = false;
typedef void (*KBDVEC)(void *);
static KBDVEC s_kbdvec = nullptr;
static void (*s_vkbderr)(void) = nullptr;
static KBDVEC s_mousevec = nullptr;
if (_video_initialized) {
Supexec(asm_screen_falcon_restore);
_video_initialized = false;
}
static void (*s_old_procterm)(void) = nullptr;
if (_200hz_initialized) {
Supexec(atari_200hz_shutdown);
_200hz_initialized = false;
}
static void exit_gem() {
if (s_app_id != -1) {
//wind_update(END_UPDATE);
if (_ikbd_initialized) {
Supexec(atari_ikbd_shutdown);
_ikbd_initialized = false;
// redraw screen
form_dial(FMD_FINISH, 0, 0, 0, 0, 0, 0, s_vdi_width, s_vdi_height);
graf_mouse(M_ON, NULL);
v_clsvwk(s_vdi_handle);
appl_exit();
}
}
static void critical_restore() {
Supexec(asm_screen_falcon_restore);
extern void AtariAudioShutdown();
extern void AtariGraphicsShutdown();
AtariAudioShutdown();
AtariGraphicsShutdown();
if (s_tt)
Supexec(asm_screen_tt_restore);
else
Supexec(asm_screen_falcon_restore);
Supexec(atari_200hz_shutdown);
Supexec(atari_ikbd_shutdown);
if (s_kbdvec && s_vkbderr && s_mousevec) {
_KBDVECS *kbdvecs = Kbdvbase();
((uintptr *)kbdvecs)[-1] = (uintptr)s_kbdvec;
kbdvecs->vkbderr = s_vkbderr;
kbdvecs->mousevec = s_mousevec;
s_kbdvec = s_mousevec = nullptr;
}
exit_gem();
}
void OSystem_Atari::initBackend() {
OSystem_Atari::OSystem_Atari() {
_fsFactory = new POSIXFilesystemFactory();
nf_init();
enum {
VDO_NO_ATARI_HW = 0xffff,
VDO_ST = 0,
VDO_STE,
VDO_TT,
VDO_FALCON,
VDO_MILAN
};
long vdo = VDO_NO_ATARI_HW<<16;
Getcookie(C__VDO, &vdo);
vdo >>= 16;
if (vdo != VDO_TT && vdo != VDO_FALCON) {
error("ScummVM requires Atari TT/Falcon compatible video");
}
s_tt = (vdo == VDO_TT);
enum {
MCH_ST = 0,
MCH_STE,
@ -110,16 +158,83 @@ void OSystem_Atari::initBackend() {
Getcookie(C__MCH, &mch);
mch >>= 16;
if (mch != MCH_FALCON && mch != MCH_ARANYM) {
error("ScummVM works only on Atari Falcon and ARAnyM");
}
if (mch == MCH_ARANYM && Getcookie(C_fVDI, NULL) == C_FOUND) {
error("Disable fVDI, ScummVM accesses Videl directly");
error("Disable fVDI, ScummVM uses XBIOS video calls");
}
nf_init();
_KBDVECS *kbdvecs = Kbdvbase();
s_kbdvec = (KBDVEC)(((uintptr *)kbdvecs)[-1]);
s_vkbderr = kbdvecs->vkbderr;
s_mousevec = kbdvecs->mousevec;
((uintptr *)kbdvecs)[-1] = (uintptr)atari_kbdvec;
kbdvecs->vkbderr = atari_vkbderr;
kbdvecs->mousevec = atari_mousevec;
Supexec(atari_200hz_init);
_timerInitialized = true;
if (s_tt)
Supexec(asm_screen_tt_save);
else
Supexec(asm_screen_falcon_save);
_videoInitialized = true;
s_old_procterm = Setexc(VEC_PROCTERM, -1);
(void)Setexc(VEC_PROCTERM, critical_restore);
}
OSystem_Atari::~OSystem_Atari() {
debug("OSystem_Atari::~OSystem_Atari()");
// _audiocdManager needs to be deleted before _mixerManager to avoid a crash.
delete _audiocdManager;
_audiocdManager = nullptr;
delete _mixerManager;
_mixerManager = nullptr;
delete _graphicsManager;
_graphicsManager = nullptr;
delete _eventManager;
_eventManager = nullptr;
delete _savefileManager;
_savefileManager = nullptr;
delete _timerManager;
_timerManager = nullptr;
delete _fsFactory;
_fsFactory = nullptr;
if (_videoInitialized) {
if (s_tt)
Supexec(asm_screen_tt_restore);
else {
Supexec(asm_screen_falcon_restore);
}
_videoInitialized = false;
}
if (_timerInitialized) {
Supexec(atari_200hz_shutdown);
_timerInitialized = false;
}
if (s_kbdvec && s_vkbderr && s_mousevec) {
_KBDVECS *kbdvecs = Kbdvbase();
((uintptr *)kbdvecs)[-1] = (uintptr)s_kbdvec;
kbdvecs->vkbderr = s_vkbderr;
kbdvecs->mousevec = s_mousevec;
s_kbdvec = s_mousevec = nullptr;
}
}
void OSystem_Atari::initBackend() {
_timerManager = new DefaultTimerManager();
_savefileManager = new DefaultSaveFileManager("saves");
@ -142,17 +257,6 @@ void OSystem_Atari::initBackend() {
// Setup and start mixer
_mixerManager->init();
Supexec(atari_ikbd_init);
_ikbd_initialized = true;
Supexec(atari_200hz_init);
_200hz_initialized = true;
Supexec(asm_screen_falcon_save);
_video_initialized = true;
(void)Setexc(VEC_PROCTERM, critical_restore);
_startTime = counter_200hz;
BaseBackend::initBackend();
@ -207,7 +311,10 @@ void OSystem_Atari::quit() {
g_system->destroy();
exit(0);
// graceful exit
(void)Setexc(VEC_PROCTERM, s_old_procterm);
exit_gem();
}
void OSystem_Atari::logMessage(LogMessageType::Type type, const char *message) {
@ -218,10 +325,13 @@ void OSystem_Atari::logMessage(LogMessageType::Type type, const char *message) {
else
output = stderr;
fputs(message, output);
static char str[1024+1];
sprintf(str, "[%08d] %s", getMillis(), message);
fputs(str, output);
fflush(output);
nf_print(message);
nf_print(str);
}
void OSystem_Atari::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
@ -272,12 +382,47 @@ OSystem *OSystem_Atari_create() {
}
int main(int argc, char *argv[]) {
s_app_id = appl_init();
if (s_app_id != -1) {
// get the ID of the current physical screen workstation
int16 dummy;
s_vdi_handle = graf_handle(&dummy, &dummy, &dummy, &dummy);
if (s_vdi_handle < 1) {
appl_exit();
error("graf_handle() failed");
}
int16 work_in[16] = {};
int16 work_out[57] = {};
// open a virtual screen workstation
v_opnvwk(work_in, &s_vdi_handle, work_out);
if (s_vdi_handle == 0) {
appl_exit();
error("v_opnvwk() failed");
}
s_vdi_width = work_out[0] + 1;
s_vdi_height = work_out[1] + 1;
graf_mouse(M_OFF, NULL);
// see https://github.com/freemint/freemint/issues/312
//wind_update(BEG_UPDATE);
}
g_system = OSystem_Atari_create();
assert(g_system);
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
g_system->destroy();
// graceful exit
(void)Setexc(VEC_PROCTERM, s_old_procterm);
exit_gem();
return res;
}

View File

@ -51,9 +51,8 @@ public:
private:
long _startTime;
bool _video_initialized = false;
bool _200hz_initialized = false;
bool _ikbd_initialized = false;
bool _videoInitialized = false;
bool _timerInitialized = false;
};
#endif

View File

@ -13,7 +13,7 @@ Yet another port?
-----------------
Yes, I am aware of the official Atari/FreeMiNT port done by KeithS over the
years (https://docs.scummvm.org/en/v2.6.1/other_platforms/atari.html). It is
years (https://docs.scummvm.org/en/v2.7.0/other_platforms/atari.html). It is
even updated every release and put on the official ScummVM website. That port
is basically just a recompiled SDL backend for our platform - that certainly
has some advantages (works in GEM, can be easily compiled for the FireBee etc.)
@ -41,34 +41,41 @@ his own backend), I decided to do the same and see whether I could do better.
And I could!
Hardware requirements
---------------------
This port requires an Atari computer with TT or Falcon compatible video modes.
Ideally accelerated with at least 4+32 MB of RAM. It runs fine also in Hatari
and ARAnyM but in case of ARAnyM don't forget to disable fVDI to show Videl
output.
Main features
-------------
- Optimized for the Atari Falcon (ideally with the CT60/CT63/CT60e but for the
less hungry games even a CT2/DFB@50 MHz or the AfterBurner040 could be enough).
- Optimized for the Atari TT/Falcon: ideally the CT60/CT63/CT60e but some games
run fine on the AfterBurner040, CT2/DFB@50 MHz, Speedy@48 MHz or even less!
- Full support for the SuperVidel, incl. the SuperBlitter (!)
- Removed features found too demanding for our platform; the most visible
change is the exclusion of the 16bpp games (those are mostly hi-res anyway)
but games in 640x480@8bpp work nicely.
but games in 640x480@8bpp work nicely (Falcon only, unfortunately).
- Direct rendering and single/triple buffering support.
- Custom (and optimal) drawing routines (especially for the cursor).
- Custom (Super)Videl resolutions for the best possible performance and visual
experience (320x240 in RGB, chunky modes with SuperVidel, 640x480@8bpp for
the overlay, ...)
- Tailored video settings for the best possible performance and visual
experience (Falcon RGB overscan, chunky modes with the SuperVidel, TT 640x480
for the overlay, ...)
- Custom (hardware based) aspect ratio correction (!)
- Support for PC keys (page up, page down, pause, F11/F12, ...) and mouse wheel
(Eiffel/Aranym only)
This makes such games as The Curse of Monkey Island better playable (on
SuperVidel nearly always also with CD (WAV) music and speech). Also, AdLib
emulation works nicely with many games without noticeable slow downs.
- AdLib emulation works nicely with many games without noticeable slow downs.
Platform-specific features outside the GUI
@ -81,8 +88,9 @@ Keyboard shortcut "CONTROL+ALT+a": immediate aspect ratio correction on/off
toggle.
"output_rate" in scummvm.ini: sample rate for mixing, can be 49170, 32780,
24585, 19668, 16390, 12292, 9834, 8195 (the lower the value, the faster the
mixing but also in worse quality). Default is 24585 Hz (16-bit, stereo).
24585, 19668, 16390, 12292, 9834, 8195 on the Falcon and 50066, 25033, 12517,
6258 on the TT (the lower the value, the faster the mixing but also worse
quality). Default is 24585/25033 Hz (16-bit, stereo).
"audio_buffer_size" in scummvm.ini: number of samples to preload. Default is
2048 which equals to about 83ms of audio lag and seems to be about right for
@ -118,13 +126,14 @@ Cons:
- screen tearing in most cases
- SuperVidel only: using C2P would be not only suboptimal (every rectangle
would be C2P'ed instead of just copy and C2P of the final screen) but poses an
additional problem as C2P requires data aligned on a 16px boundary and
ScummVM supplies arbitrarily-sized rectangles (this is solvable by custom
Surface allocation but it's not bullet-proof). In theory I could implement
direct rendering for the Falcon hicolor (320x240@16bpp) but this creates
another set of issues like when palette would be updated but not the whole
screen - so some rectangles would be rendered in old palette and some in new.
would be C2P'ed instead of multiple copying and just one C2P of the final
screen) but poses an additional problem as C2P requires data aligned on a
16px boundary and ScummVM supplies arbitrarily-sized rectangles (this is
solvable by custom Surface allocation but it's not bullet-proof). In theory I
could implement direct rendering for the Falcon hicolor (320x240@16bpp) but
this creates another set of issues like when palette would be updated but not
the whole screen - so some rectangles would be rendered in old palette and
some in new.
SuperBlitter used: sometimes (when ScummVM allocates surface via its create()
function; custom/small buffers originating in the engine code are still copied
@ -192,8 +201,7 @@ SuperVidel and SuperBlitter
As mentioned, this port uses SuperVidel and its SuperBlitter heavily. That
means that if the SuperVidel is detected, it does the following:
- patches all 8bpp VGA resolutions to chunky ones, rendering all C2P routines
useless
- uses 8bpp chunky resolutions
- patches all surface addresses with OR'ing 0xA0000000, i.e. using SV RAM
instead of slow ST RAM (and even instead of TT RAM for allowing pure
@ -205,6 +213,17 @@ means that if the SuperVidel is detected, it does the following:
and makes a *huge* difference for 640x480 fullscreen updates.
Audio mixing
------------
ScummVM works internally with 16-bit stereo samples. This mode is not available
on the TT so a substitute solution must be used. This solution is called STFA
by The Removers: http://removers.free.fr/softs/stfa.php. Install, activate STFA
BIOS in the CPX, done. Now you have 16-bit DMA available, too but beware, it is
also quite CPU demanding so very few games can actually make use of it (see the
chapter about audio performance considerations below).
Performance considerations/pitfalls
-----------------------------------
@ -233,11 +252,23 @@ is (by definition) the case of animated intros, especially those in 640x480.
MIDI vs. AdLib vs. sampled music
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It could seem that sample music replay must be the most demanding one but on the
contrary! _Always_ choose a CD version of a game (with *.wav tracks) to any
It could seem that sample music replay must be the most demanding one but on
the contrary! Always choose a CD version of a game (with *.wav tracks) to any
other version. With one exception: if you have a native MIDI device able to
replay the given game's MIDI notes (using the STMIDI plugin). MIDI emulation
(synthesis) can easily eat as much as 50% of all used CPU time.
replay the given game's MIDI notes (using the STMIDI plugin).
MIDI emulation (synthesis) can easily eat as much as 50% of all used CPU time
(on the CT60). By default, this port uses the MAME OPL emulation (which is said
to be fastest but also least accurate) but some engines require the DOSBOX one
which is even more demanding. By the way, you can put "FM_high_quality=true"
or "FM_medium_quality=true" into scummvm.ini if you want to experiment with a
better quality synthesis, otherwise the lowest quality will be used (applies
for MAME OPL only).
On the TT, in 95% of cases it makes sense to enable music only if you have a
native MIDI synthesizer (like mt32-pi: https://github.com/dwhinham/mt32-pi);
STFA is usually slow to mix samples, too => mute it (see below) or don't
install STFA (same effect).
CD music slows everything down
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -283,18 +314,41 @@ loading time. To speed things up in other cases, the "fat" version is
distributed with repackaged theme files with compression level zero.
"Slim" vs. "Fat" version
------------------------
As a further optimisation step, a 030-only version of ScummVM is provided,
aimed at accelerated TT and Falcon machines with the 68030 CPU. It further
restricts features but also improves performance:
- compiled with -m68030 => 68030/68882-specific optimisations enabled
- disabled 040+/SuperVidel code => faster code path for blitting
- doesn't support hires (640x480) games => smaller executable size
- overlay is rendered in 16 colours => faster redraw
- overlay during gameplay has no game backround => ever faster redraw
- overlay doesn't support alternative themes => faster loading time
Known issues
------------
- aspect ratio correction works on RGB only (yet)
- SuperVidel's DVI output is stretched when in 320x200 or 640x400; I'll wait
for other people's experiences, maybe only my LCD is so lame.
- adding a game in TOS and loading it in FreeMiNT (and vice versa) generates
incompatible paths. Either use only one system or edit scummvm.ini and set
there only relative paths (mintlib bug/limitation).
- when run on TT, screen contains horizontal black lines. That is due to the
fact that TT offers only 320x480 in 256 colours. Possibly fixable by a Timer
B interrupt.
- tooltips in overlay are sometimes drawn with corrupted background.
- the talkie version of MI1 needs to be merged from two sources: first generate
the DOS version and then additionally also the flac version. Then convert all
*.flac files into *.wav and replace monkey.sof (flac) with monster.sou (DOS).
@ -306,11 +360,11 @@ Known issues
Future plans
------------
- aspect ratio correction for VGA/SuperVidel
- aspect ratio correction for TT/VGA/SuperVidel
- unified file paths in scummvm.ini
- DSP-based sample mixer
- DSP-based sample mixer (WAV, FLAC, MP2)
- avoid loading music/speech files (and thus slowing down everything) if muted
@ -320,24 +374,10 @@ Future plans
- using LDG or Thorsten Otto's sharedlibs: https://tho-otto.de/sharedlibs.php
for game engine plugins to relieve the huge binary size
- add support for the TT030; this would be easily possible when I rewrite the
renderer with a more flexible resolution switching
- don't hardcode some of the buffers for cacheing purposes, determine the size
based on amount of free RAM
- true audio CD support via MetaDOS API
- OPL2LPT and Retrowave support (if I manage to purchase it somewhere)
- engines based on Graphics::Screen don't have to use my chunky buffer (however
it may be tricky to detect this situation)
- C2P could support 4- and 6-bit depth
- increase file buffer size with setvbuf or by using
Common::wrapBufferedWriteStream and disabling stdio buffering
Closing words
-------------

13
configure vendored
View File

@ -3652,13 +3652,15 @@ if test -n "$_host"; then
if test "$_optimizations" = "yes"; then
# --enable-release, --enable-optimizations
append_var CXXFLAGS "-fomit-frame-pointer"
append_var CXXFLAGS "-fno-exceptions"
append_var CXXFLAGS "-ffast-math"
fi
# auto -> no
if test "$_release_build" = "yes"; then
# --enable-release
append_var DEFINES "-DNDEBUG"
append_var DEFINES "-DDISABLE_TEXT_CONSOLE"
#append_var DEFINES "-DDISABLE_TEXT_CONSOLE"
append_var CXXFLAGS "-I$HOME/gnu-tools/m68000/m68k-atari-mint/sys-root/opt/mintlib-dlmalloc/include"
append_var LDFLAGS "-L$HOME/gnu-tools/m68000/m68k-atari-mint/sys-root/opt/mintlib-dlmalloc/lib/m68020-60"
fi
@ -3955,10 +3957,11 @@ case $_backend in
;;
atari)
define_in_config_if_yes yes "ATARI"
append_var DEFINES "-DDISABLE_LAUNCHERDISPLAY_GRID"
append_var DEFINES "-DDISABLE_SID"
append_var DEFINES "-DDISABLE_NES_APU"
#append_var DEFINES "-DDISABLE_DOSBOX_OPL"
append_var DEFINES "-DDISABLE_LAUNCHERDISPLAY_GRID"
append_var DEFINES "-DDISABLE_SID"
append_var DEFINES "-DDISABLE_NES_APU"
#append_var DEFINES "-DDISABLE_DOSBOX_OPL"
append_var LIBS "-lgem"
;;
dc)
append_var INCLUDES '-I$(srcdir)/backends/platform/dc'

View File

@ -119,7 +119,7 @@ void Surface::create(int16 width, int16 height, const PixelFormat &f) {
if (width && height) {
#ifdef USE_SV_BLITTER
if (hasSuperVidel()) {
if (hasSuperVidel() && w >= 64 && h >= 64) {
pixels = (void *)ct60_vmalloc(height * pitch);
if (!pixels)