BACKENDS: ATARI: Add new backend (graphics, mixer, platform)

Compile as:

./configure --backend=atari --host=m68k-atari-mint --enable-release --disable-mt32emu --disable-lua --disable-nuked-opl --disable-16bit --disable-scalers --disable-translation --disable-eventrecorder --disable-tts --disable-bink --opengl-mode=none --enable-verbose-build --prefix=/usr --bindir=/ --datarootdir=share --datadir=data && make -j 16 && m68k-atari-mint-flags -S -r ./scummvm && make install DESTDIR=$PWD/_release/ && mv $PWD/_release/scummvm $PWD/_release/scummvm.ttp
This commit is contained in:
Miro Kropacek 2023-02-05 17:05:01 +01:00 committed by Eugene Sandulenko
parent 9285e5a66e
commit 4d21a496d2
20 changed files with 4698 additions and 0 deletions

View File

@ -0,0 +1,354 @@
/* 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/>.
*
*/
.globl _asm_screen_tt_save
.globl _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
.globl _vbl_counter
.text
| extern void asm_screen_tt_save(void);
|
_asm_screen_tt_save:
bsr wait_vbl | avoid flickering
lea 0xffff8400.w,a0
lea save_pal,a1
moveq #256/2-1,d0
tt_save_loop:
move.l (a0)+,(a1)+
dbra d0,tt_save_loop
lea save_video,a1
move.l 0xffff8200.w,(a1)+ | vidhm
move.w 0xffff820c.w,(a1)+ | vidl
move.w 0xffff8262.w,(a1)+ | tt shifter
rts
| extern void asm_screen_falcon_save(void);
|
_asm_screen_falcon_save:
movem.l d2-d7/a2,-(sp)
bsr wait_vbl | avoid flickering
lea 0xffff9800.w,a0 | save falcon palette
lea save_pal,a1 |
moveq #256/2-1,d7 |
|
falcon_save_loop:
move.l (a0)+,(a1)+ |
move.l (a0)+,(a1)+ |
dbra d7,falcon_save_loop |
movem.l 0xffff8240.w,d0-d7 | save st palette
movem.l d0-d7,(a1) |
lea save_video,a0
move.l 0xffff8200.w,(a0)+ | vidhm
move.w 0xffff820c.w,(a0)+ | vidl
move.l 0xffff8282.w,(a0)+ | h-regs
move.l 0xffff8286.w,(a0)+ |
move.l 0xffff828a.w,(a0)+ |
move.l 0xffff82a2.w,(a0)+ | v-regs
move.l 0xffff82a6.w,(a0)+ |
move.l 0xffff82aa.w,(a0)+ |
move.w 0xffff82c0.w,(a0)+ | vco
move.w 0xffff82c2.w,(a0)+ | c_s
move.l 0xffff820e.w,(a0)+ | offset+width
move.w 0xffff820a.w,(a0)+ | sync
move.b 0xffff8265.w,(a0)+ | p_o
cmpi.w #0xb0,0xffff8282.w | st(e) / falcon test
sle (a0)+ | it's a falcon resolution
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
| extern void asm_screen_tt_restore(void);
|
_asm_screen_tt_restore:
bsr wait_vbl | avoid flickering
lea save_video,a1
move.l (a1)+,0xffff8200.w | vidhm
move.w (a1)+,0xffff820c.w | vidl
move.w (a1)+,0xffff8262.w | tt shifter
lea save_pal,a0
lea 0xffff8400.w,a1
moveq #256/2-1,d0
.loop: move.l (a0)+,(a1)+
dbra d0,.loop
rts
| extern void asm_screen_falcon_restore(void);
|
_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
move.l (a0)+,0xffff8200.w | videobase_address:h&m
move.w (a0)+,0xffff820c.w | l
move.l (a0)+,0xffff8282.w | h-regs
move.l (a0)+,0xffff8286.w |
move.l (a0)+,0xffff828a.w |
move.l (a0)+,0xffff82a2.w | v-regs
move.l (a0)+,0xffff82a6.w |
move.l (a0)+,0xffff82aa.w |
move.w (a0)+,0xffff82c0.w | vco
move.w (a0)+,0xffff82c2.w | c_s
move.l (a0)+,0xffff820e.w | offset+width
move.w (a0)+,0xffff820a.w | sync
move.b (a0)+,0xffff8265.w | p_o
tst.b (a0)+ | st(e) compatible mode?
bne falcon_restore_st_comp | yes
falcon_restore_falcon:
move.l a0,-(sp)
bsr wait_vbl | Patch to avoid
clr.w 0xffff8266.w | monochrome sync errors
bsr wait_vbl | (ripped from
move.l (sp)+,a0 | FreeMiNT kernel,
move.w (a0),0xffff8266.w | by Draco/Yescrew)
bra falcon_restore_restored
falcon_restore_st_comp:
move.w (a0)+,0xffff8266.w | falcon-shift
move.w (a0),0xffff8260.w | st-shift
lea save_video,a0
move.w 32(a0),0xffff82c2.w | c_s
move.l 34(a0),0xffff820e.w | offset+width
falcon_restore_restored:
lea save_pal,a0 | restore falcon palette
lea 0xffff9800.w,a1 |
moveq #128-1,d7 |
|
falcon_restore_loop:
move.l (a0)+,(a1)+ |
move.l (a0)+,(a1)+ |
dbra d7,falcon_restore_loop |
movem.l (a0),d0-d7 | restore st palette
movem.l d0-d7,0xffff8240.w |
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 uint32 pPalette[256]);
|
_asm_screen_set_falcon_palette:
move.l (4,sp),a0
lea pending_palette,a1
moveq #256/2-1,d0
set_falcon_palette_loop:
move.l (a0)+,(a1)+
move.l (a0)+,(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
addq.l #1,_vbl_counter | to avoid accessing protected memory
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:
ds.b 32+12+2 | old video regs (size of falcon regs)
_vbl_counter:
ds.l 1

View File

@ -0,0 +1,70 @@
/* 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_ASM_H
#define BACKENDS_GRAPHICS_ATARI_ASM_H
#include "common/scummsys.h"
extern "C" {
/**
* Save Atari TT video registers.
*/
void asm_screen_tt_save(void);
/**
* Save Atari Falcon video registers.
*/
void asm_screen_falcon_save(void);
/**
* Restore Atari TT video registers.
*/
void asm_screen_tt_restore(void);
/**
* Restore Atari Falcon video registers.
*/
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 00000000 BBBBBBbb)
*/
void asm_screen_set_falcon_palette(const uint32 pPalette[256]);
/**
* 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

@ -0,0 +1,53 @@
/* 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_SUPERBLITTER_H
#define BACKENDS_GRAPHICS_ATARI_SUPERBLITTER_H
#include <mint/trap14.h>
#define ct60_vm(mode, value) (long)trap_14_wwl((short)0xc60e, (short)(mode), (long)(value))
#define ct60_vmalloc(value) ct60_vm(0, value)
#define ct60_vmfree(value) ct60_vm(1, value)
// bits 26:0
#define SV_BLITTER_SRC1 ((volatile long*)0x80010058)
#define SV_BLITTER_SRC2 ((volatile long*)0x8001005C)
#define SV_BLITTER_DST ((volatile long*)0x80010060)
// The amount of bytes that are to be copied in a horizontal line, minus 1
#define SV_BLITTER_COUNT ((volatile long*)0x80010064)
// The amount of bytes that are to be added to the line start adress after a line has been copied, in order to reach the next one
#define SV_BLITTER_SRC1_OFFSET ((volatile long*)0x80010068)
#define SV_BLITTER_SRC2_OFFSET ((volatile long*)0x8001006C)
#define SV_BLITTER_DST_OFFSET ((volatile long*)0x80010070)
// bits 11:0 - The amount of horizontal lines to do
#define SV_BLITTER_MASK_AND_LINES ((volatile long*)0x80010074)
// bit 0 - busy / start
// bits 4:1 - blit mode
#define SV_BLITTER_CONTROL ((volatile long*)0x80010078)
// bits 9:0
#define SV_VERSION ((volatile long*)0x8001007C)
// bit 0 - empty (read only)
// bit 1 - full (read only)
// bits 31:0 - data (write only)
#define SV_BLITTER_FIFO ((volatile long*)0x80010080)
#endif

View File

@ -0,0 +1,201 @@
/* 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_SUPERVIDEL_H
#define BACKENDS_GRAPHICS_ATARI_SUPERVIDEL_H
#define USE_SV_BLITTER // TODO: into configure?
#include "backends/graphics/atari/atari-graphics.h"
#include <cstring>
#include <mint/osbind.h>
#ifdef USE_SV_BLITTER
#include "backends/graphics/atari/atari-graphics-superblitter.h"
#endif
#include "backends/graphics/atari/videl-resolutions.h"
#include "common/scummsys.h"
#include "common/textconsole.h" // for error()
class AtariSuperVidelManager : public AtariGraphicsManager {
public:
AtariSuperVidelManager() {
#ifdef USE_SV_BLITTER
_fwVersion = *SV_VERSION & 0x01ff;
debug("SuperVidel FW Revision: %d, using %s", _fwVersion, _fwVersion >= 9
? "fast async FIFO" : "slower sync blitting" );
#endif
for (int i = 0; i < SCREENS; ++i) {
if (!allocateAtariSurface(_screen[i], _screenSurface,
SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8,
MX_STRAM, 0xA0000000))
error("Failed to allocate screen memory in ST RAM");
_screenAligned[i] = (byte*)_screenSurface.getPixels();
}
_screenSurface.setPixels(_screenAligned[getDefaultGraphicsMode() <= 1 ? FRONT_BUFFER : BACK_BUFFER1]);
if (!allocateAtariSurface(_chunkyBuffer, _chunkySurface,
SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8,
MX_PREFTTRAM))
error("Failed to allocate chunky buffer memory in ST/TT RAM");
if (!allocateAtariSurface(_overlayScreen, _screenOverlaySurface,
getOverlayWidth(), getOverlayHeight(), getOverlayFormat(),
MX_STRAM, 0xA0000000))
error("Failed to allocate overlay memory in ST RAM");
if (!allocateAtariSurface(_overlayBuffer, _overlaySurface,
getOverlayWidth(), getOverlayHeight(), getOverlayFormat(),
MX_PREFTTRAM))
error("Failed to allocate overlay buffer memory in ST/TT RAM");
// 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;
}
}
~AtariSuperVidelManager() {
#ifdef USE_SV_BLITTER
ct60_vmfree(_chunkyBuffer);
#else
Mfree(_chunkyBuffer);
#endif
_chunkyBuffer = nullptr;
#ifdef USE_SV_BLITTER
ct60_vmfree(_overlayBuffer);
#else
Mfree(_overlayBuffer);
#endif
_overlayBuffer = nullptr;
}
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override {
static const OSystem::GraphicsMode graphicsModes[] = {
{"direct", "Direct rendering", 0},
{"single", "Single buffering", 1},
{"double", "Double buffering", 2},
{"triple", "Triple buffering", 3},
{nullptr, nullptr, 0 }
};
return graphicsModes;
}
int16 getOverlayHeight() const override { return 2 * OVERLAY_HEIGHT; }
int16 getOverlayWidth() const override { return 2 * OVERLAY_WIDTH; }
private:
virtual void* allocFast(size_t bytes) const override {
#ifdef USE_SV_BLITTER
return (void*)ct60_vmalloc(bytes);
#else
return (void*)Mxalloc(bytes, MX_PREFTTRAM);
#endif
}
void copySurfaceToSurface(const Graphics::Surface &srcSurface, Graphics::Surface &dstSurface) const override {
#ifdef USE_SV_BLITTER
if (_fwVersion >= 9) {
*SV_BLITTER_FIFO = (long)srcSurface.getPixels(); // SV_BLITTER_SRC1
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2
*SV_BLITTER_FIFO = (long)dstSurface.getPixels(); // SV_BLITTER_DST
*SV_BLITTER_FIFO = srcSurface.w - 1; // SV_BLITTER_COUNT
*SV_BLITTER_FIFO = srcSurface.pitch; // SV_BLITTER_SRC1_OFFSET
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2_OFFSET
*SV_BLITTER_FIFO = dstSurface.pitch; // SV_BLITTER_DST_OFFSET
*SV_BLITTER_FIFO = srcSurface.h; // SV_BLITTER_MASK_AND_LINES
*SV_BLITTER_FIFO = 0x01; // SV_BLITTER_CONTROL
} else {
sync();
*SV_BLITTER_SRC1 = (long)srcSurface.getPixels();
*SV_BLITTER_SRC2 = 0x00000000;
*SV_BLITTER_DST = (long)dstSurface.getPixels();
*SV_BLITTER_COUNT = srcSurface.w - 1;
*SV_BLITTER_SRC1_OFFSET = srcSurface.pitch;
*SV_BLITTER_SRC2_OFFSET = 0x00000000;
*SV_BLITTER_DST_OFFSET = dstSurface.pitch;
*SV_BLITTER_MASK_AND_LINES = srcSurface.h;
*SV_BLITTER_CONTROL = 0x01;
}
#else
memcpy(dstSurface.getPixels(), srcSurface.getPixels(), srcSurface.h * srcSurface.pitch);
#endif
}
void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, Graphics::Surface &dstSurface,
const Common::Rect &subRect) const override {
#ifdef USE_SV_BLITTER
if (_fwVersion >= 9) {
*SV_BLITTER_FIFO = (long)srcSurface.getBasePtr(subRect.left, subRect.top); // SV_BLITTER_SRC1
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2
*SV_BLITTER_FIFO = (long)dstSurface.getBasePtr(destX, destY); // SV_BLITTER_DST
*SV_BLITTER_FIFO = subRect.width() - 1; // SV_BLITTER_COUNT
*SV_BLITTER_FIFO = srcSurface.pitch; // SV_BLITTER_SRC1_OFFSET
*SV_BLITTER_FIFO = 0x00000000; // SV_BLITTER_SRC2_OFFSET
*SV_BLITTER_FIFO = dstSurface.pitch; // SV_BLITTER_DST_OFFSET
*SV_BLITTER_FIFO = subRect.height(); // SV_BLITTER_MASK_AND_LINES
*SV_BLITTER_FIFO = 0x01; // SV_BLITTER_CONTROL
} else {
sync();
*SV_BLITTER_SRC1 = (long)srcSurface.getBasePtr(subRect.left, subRect.top);
*SV_BLITTER_SRC2 = 0x00000000;
*SV_BLITTER_DST = (long)dstSurface.getBasePtr(destX, destY);
*SV_BLITTER_COUNT = subRect.width() - 1;
*SV_BLITTER_SRC1_OFFSET = srcSurface.pitch;
*SV_BLITTER_SRC2_OFFSET = 0x00000000;
*SV_BLITTER_DST_OFFSET = dstSurface.pitch;
*SV_BLITTER_MASK_AND_LINES = subRect.height();
*SV_BLITTER_CONTROL = 0x01;
}
#else
dstSurface.copyRectToSurface(srcSurface, destX, destY, subRect);
#endif
}
void copyRectToSurfaceWithKey(const Graphics::Surface &srcSurface, int destX, int destY, Graphics::Surface &dstSurface,
const Common::Rect &subRect, uint32 key) const override {
sync();
dstSurface.copyRectToSurfaceWithKey(srcSurface, destX, destY, subRect, key);
}
virtual void sync() const override {
#ifdef USE_SV_BLITTER
// while FIFO not empty...
if (_fwVersion >= 9)
while (!(*SV_BLITTER_FIFO & 1));
// while busy blitting...
while (*SV_BLITTER_CONTROL & 1);
#endif
}
#ifdef USE_SV_BLITTER
int _fwVersion = 0;
#endif
};
#endif

View File

@ -0,0 +1,162 @@
/* 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_H
#define BACKENDS_GRAPHICS_ATARI_VIDEL_H
#include "backends/graphics/atari/atari-graphics.h"
#include <mint/osbind.h>
#include "backends/graphics/atari/atari_c2p-asm.h"
#include "common/system.h"
#include "common/textconsole.h" // for error()
class AtariVidelManager : public AtariGraphicsManager {
public:
AtariVidelManager() {
for (int i = 0; i < SCREENS; ++i) {
if (!allocateAtariSurface(_screen[i], _screenSurface, SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8, MX_STRAM))
error("Failed to allocate screen memory in ST RAM");
_screenAligned[i] = (byte*)_screenSurface.getPixels();
}
_screenSurface.setPixels(_screenAligned[getDefaultGraphicsMode() <= 1 ? FRONT_BUFFER : BACK_BUFFER1]);
if (!allocateAtariSurface(_chunkyBuffer, _chunkySurface, SCREEN_WIDTH, SCREEN_HEIGHT, PIXELFORMAT8, MX_PREFTTRAM))
error("Failed to allocate chunky buffer memory in ST/TT RAM");
if (!allocateAtariSurface(_overlayScreen, _screenOverlaySurface, getOverlayWidth(), getOverlayHeight(),
getOverlayFormat(), MX_STRAM))
error("Failed to allocate overlay memory in ST RAM");
if (!allocateAtariSurface(_overlayBuffer, _overlaySurface, getOverlayWidth(), getOverlayHeight(),
getOverlayFormat(), MX_PREFTTRAM))
error("Failed to allocate overlay buffer memory in ST/TT RAM");
}
~AtariVidelManager() {
Mfree(_chunkyBuffer);
_chunkyBuffer = nullptr;
Mfree(_overlayBuffer);
_overlayBuffer = nullptr;
}
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override {
static const OSystem::GraphicsMode graphicsModes[] = {
{"single", "Single buffering", 1},
{"double", "Double buffering", 2},
{"triple", "Triple buffering", 3},
{nullptr, nullptr, 0 }
};
return graphicsModes;
}
OSystem::TransactionError endGFXTransaction() override {
int error = OSystem::TransactionError::kTransactionSuccess;
if (_pendingState.mode == GraphicsMode::DirectRendering)
error |= OSystem::TransactionError::kTransactionModeSwitchFailed;
if (error != OSystem::TransactionError::kTransactionSuccess) {
// all our errors are fatal but engine.cpp takes only this one seriously
error |= OSystem::TransactionError::kTransactionSizeChangeFailed;
return static_cast<OSystem::TransactionError>(error);
}
return AtariGraphicsManager::endGFXTransaction();
}
int16 getOverlayHeight() const override { return _vgaMonitor ? OVERLAY_HEIGHT : 2 * OVERLAY_HEIGHT; }
int16 getOverlayWidth() const override { return _vgaMonitor ? OVERLAY_WIDTH : 2 * OVERLAY_WIDTH; }
private:
virtual void* allocFast(size_t bytes) const override {
return (void*)Mxalloc(bytes, MX_PREFTTRAM);
}
void copySurfaceToSurface(const Graphics::Surface &srcSurface, Graphics::Surface &dstSurface) const override {
asm_c2p1x1_8(
(const byte*)srcSurface.getPixels(),
(const byte*)srcSurface.getBasePtr(srcSurface.w, srcSurface.h-1),
(byte*)dstSurface.getPixels());
}
void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY,
Graphics::Surface &dstSurface, const Common::Rect &subRect) const override {
// 'pChunkyEnd' is a delicate parameter: the c2p routine compares it to the address register
// 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
asm_c2p1x1_8_rect(
(const byte*)srcSurface.getBasePtr(subRect.left, subRect.top),
(const byte*)srcSurface.getBasePtr(subRect.right, subRect.bottom-1),
subRect.width(),
srcSurface.pitch,
(byte*)dstSurface.getBasePtr(destX, destY),
dstSurface.pitch);
}
// TODO: allow specifying different background than _chunkySurface?
void copyRectToSurfaceWithKey(const Graphics::Surface &srcSurface, int destX, int destY,
Graphics::Surface &dstSurface, const Common::Rect &subRect, uint32 key) 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
backgroundRect.moveTo(backgroundRect.left & 0xfff0, backgroundRect.top);
const int deltaX = destX - backgroundRect.left;
backgroundRect.right = (backgroundRect.right + deltaX + 15) & 0xfff0;
if (backgroundRect.right > _chunkySurface.w)
backgroundRect.right = _chunkySurface.w;
static Graphics::Surface cachedSurface;
if (cachedSurface.w != backgroundRect.width() || cachedSurface.h != backgroundRect.height()) {
cachedSurface.create(
backgroundRect.width(),
backgroundRect.height(),
_chunkySurface.format);
}
// copy background
cachedSurface.copyRectToSurface(_chunkySurface, 0, 0, backgroundRect);
// copy cursor
cachedSurface.copyRectToSurfaceWithKey(srcSurface, deltaX, 0, subRect, key);
copyRectToSurface(
cachedSurface,
backgroundRect.left, backgroundRect.top,
dstSurface,
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

@ -0,0 +1,272 @@
/* 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_H
#define BACKENDS_GRAPHICS_ATARI_H
#include "backends/graphics/graphics.h"
#include "common/array.h"
#include "common/events.h"
#include "common/rect.h"
#include "graphics/surface.h"
// maximum screen dimensions
constexpr int SCREEN_WIDTH = 640;
constexpr int SCREEN_HEIGHT = 480;
// minimum overlay dimensions
constexpr int OVERLAY_WIDTH = 320;
constexpr int OVERLAY_HEIGHT = 240;
class AtariGraphicsManager : public GraphicsManager, Common::EventObserver {
public:
AtariGraphicsManager();
virtual ~AtariGraphicsManager();
bool hasFeature(OSystem::Feature f) const override;
void setFeatureState(OSystem::Feature f, bool enable) override;
bool getFeatureState(OSystem::Feature f) const override;
int getDefaultGraphicsMode() const override { return (int)GraphicsMode::TripleBuffering; }
bool setGraphicsMode(int mode, uint flags = OSystem::kGfxModeNoFlags) override;
int getGraphicsMode() const override { return (int)_currentState.mode; }
void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) override;
int getScreenChangeID() const override { return 0; }
void beginGFXTransaction() override;
OSystem::TransactionError endGFXTransaction() override;
int16 getHeight() const override { return _currentState.height; }
int16 getWidth() const override { return _currentState.width; }
void setPalette(const byte *colors, uint start, uint num) override;
void grabPalette(byte *colors, uint start, uint num) const override;
void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
Graphics::Surface *lockScreen() override;
void unlockScreen() override;
void fillScreen(uint32 col) override;
void updateScreen() override;
void setShakePos(int shakeXOffset, int shakeYOffset) override;
void setFocusRectangle(const Common::Rect& rect) override {}
void clearFocusRectangle() override {}
void showOverlay(bool inGUI) override;
void hideOverlay() override;
bool isOverlayVisible() const override { return _overlayVisible; }
Graphics::PixelFormat getOverlayFormat() const override { return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); }
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;
bool showMouse(bool visible) override;
void warpMouse(int x, int y) override;
void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor,
bool dontScale = false, const Graphics::PixelFormat *format = NULL, const byte *mask = NULL) override;
void setCursorPalette(const byte *colors, uint start, uint num) override;
Common::Point getMousePosition() const { return _cursor.getPosition(); }
void updateMousePosition(int deltaX, int deltaY);
bool notifyEvent(const Common::Event &event) override;
Common::Keymap *getKeymap() const;
protected:
const Graphics::PixelFormat PIXELFORMAT8 = Graphics::PixelFormat::createFormatCLUT8();
const Graphics::PixelFormat PIXELFORMAT16 = getOverlayFormat();
bool allocateAtariSurface(byte *&buf, Graphics::Surface &surface,
int width, int height, const Graphics::PixelFormat &format,
int mode, uintptr mask = 0x00000000);
bool _vgaMonitor = true;
enum class GraphicsMode : int {
DirectRendering,
SingleBuffering,
DoubleBuffering,
TripleBuffering
};
struct GraphicsState {
bool operator==(const GraphicsState &other) const {
return mode == other.mode
&& width == other.width
&& height == other.height
&& format == other.format;
}
bool operator!=(const GraphicsState &other) const {
return !(*this == other);
}
GraphicsMode mode;
int width;
int height;
Graphics::PixelFormat format;
};
GraphicsState _pendingState = {};
static const int SCREENS = 3;
static const int FRONT_BUFFER = 0;
static const int BACK_BUFFER1 = 1;
static const int BACK_BUFFER2 = 2;
byte *_screen[SCREENS] = {}; // for Mfree() purposes only
byte *_screenAligned[SCREENS] = {};
Graphics::Surface _screenSurface;
byte *_chunkyBuffer = nullptr; // for Mfree() purposes only
Graphics::Surface _chunkySurface;
byte *_overlayScreen = nullptr; // for Mfree() purposes only
Graphics::Surface _screenOverlaySurface;
byte *_overlayBuffer = nullptr; // for Mfree() purposes only
Graphics::Surface _overlaySurface;
private:
enum CustomEventAction {
kActionToggleAspectRatioCorrection = 100,
};
void setVidelResolution() const;
void waitForVbl() const;
bool updateOverlay();
bool updateDirectBuffer();
bool updateSingleBuffer();
bool updateDoubleAndTripleBuffer();
virtual void* allocFast(size_t bytes) const = 0;
virtual void copySurfaceToSurface(const Graphics::Surface &srcSurface, Graphics::Surface &dstSurface) const = 0;
virtual void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY,
Graphics::Surface &dstSurface, const Common::Rect &subRect) const = 0;
virtual void copyRectToSurfaceWithKey(const Graphics::Surface &srcSurface, int destX, int destY,
Graphics::Surface &dstSurface, const Common::Rect &subRect, uint32 key) const = 0;
virtual void alignRect(const Graphics::Surface &srcSurface, Common::Rect &rect) const {}
virtual void sync() const {}
enum class ScaleMode {
NONE,
UPSCALE,
DOWNSCALE
};
void copySurface8ToSurface16(const Graphics::Surface &srcSurface, const byte *srcPalette,
Graphics::Surface &dstSurface, int destX, int destY,
const Common::Rect subRect, ScaleMode scaleMode) const;
void copySurface8ToSurface16WithKey(const Graphics::Surface &srcSurface, const byte* srcPalette,
Graphics::Surface &dstSurface, int destX, int destY,
const Common::Rect subRect, uint32 key) const;
void handleModifiedRect(const Graphics::Surface &surface, Common::Rect rect, Common::Array<Common::Rect> &rects) const;
void updateCursorRect();
bool _aspectRatioCorrection = false;
bool _oldAspectRatioCorrection = false;
bool _vsync = true;
GraphicsState _currentState = {};
enum PendingScreenChange {
kPendingScreenChangeNone = 0,
kPendingScreenChangeOverlay = 1<<0,
kPendingScreenChangeScreen = 1<<1,
kPendingScreenChangePalette = 1<<2
};
int _pendingScreenChange = kPendingScreenChangeNone;
bool _screenModified = false; // double/triple buffering only
Common::Rect _modifiedScreenRect; // direct rendering only
Common::Array<Common::Rect> _modifiedChunkyRects;
bool _overlayVisible = false;
Common::Array<Common::Rect> _modifiedOverlayRects;
struct Cursor {
void update(const Graphics::Surface &screen);
bool isModified() const {
return surfaceChanged || positionChanged;
}
bool visible = false;
// position
Common::Point getPosition() const {
return Common::Point(x, y);
}
void setPosition(int x_, int y_, bool override = false) {
if (x == x_ && y == y_)
return;
if (!visible && !override)
return;
x = x_;
y = y_;
positionChanged = true;
}
void updatePosition(int deltaX, int deltaY, const Graphics::Surface &screen);
bool positionChanged = false;
void swap() {
const int tmpX = oldX;
const int tmpY = oldY;
oldX = x;
oldY = y;
x = tmpX;
y = tmpY;
positionChanged = false;
}
// surface
void setSurface(const void *buf, int w, int h, int _hotspotX, int _hotspotY, uint32 _keycolor, const Graphics::PixelFormat &format);
bool surfaceChanged = false;
Graphics::Surface surface;
uint32 keycolor;
// rects (valid only if !outOfScreen)
bool outOfScreen = true;
Common::Rect srcRect;
Common::Rect dstRect;
// palette (only used for 16bpp screen surfaces)
byte palette[256*3] = {};
private:
int x = -1, y = -1;
int oldX = -1, oldY = -1;
int hotspotX;
int hotspotY;
} _cursor;
Common::Rect _oldCursorRect;
byte _palette[256*3] = {};
};
#endif

View File

@ -0,0 +1,474 @@
/* 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/>.
*
*/
| C2P by Mikael Kalms (public domain)
| See https://github.com/Kalmalyzer/kalms-c2p
.globl _asm_c2p1x1_8
.globl _asm_c2p1x1_8_rect
.text
| void asm_c2p1x1_8(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
_asm_c2p1x1_8:
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)+,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_start
c2p1x1_8_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
c2p1x1_8_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_pix16
move.l a3,(a1)+
move.l a4,(a1)+
move.l a5,(a1)+
move.l a6,(a1)+
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
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
lea (a0,d0.l),a2 | a2: end of first src line
lea (a1,d0.l),a7 | a7: end of first dst line
move.l d1,screen_pitch
sub.l d0,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)+,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_rect_start
c2p1x1_8_rect_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_rect_start
add.l (screen_offset,pc),a1
add.l (screen_pitch,pc),a7
c2p1x1_8_rect_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 | end of src line?
bne c2p1x1_8_rect_pix16
cmp.l (chunky_end,pc),a2
beq.s c2p1x1_8_rect_done
add.l (chunky_offset,pc),a0
add.l (chunky_pitch,pc),a2
bra c2p1x1_8_rect_pix16
c2p1x1_8_rect_done:
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
| place it within reach of 32K (PC relative)
screen_pitch:
ds.l 1
screen_offset:
ds.l 1
chunky_pitch:
ds.l 1
chunky_offset:
ds.l 1
chunky_end:
ds.l 1
.bss
.even
old_sp: ds.l 1

View File

@ -0,0 +1,54 @@
/* 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_C2P_ASM_H
#define BACKENDS_GRAPHICS_ATARI_C2P_ASM_H
#include "common/scummsys.h"
extern "C" {
/**
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into eight bitplanes.
* 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 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 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_8_rect(const byte *pChunky, const byte *pChunkyEnd, uint32 chunkyWidth, uint32 chunkyPitch, byte *pScreen, uint32 screenPitch);
}
#endif

View File

@ -0,0 +1,262 @@
/* 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_320x240x16_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, 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x2c,
0x00, 0xf0, 0x00, 0x03, 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, 0x38, 0x00, 0x99,
0x00, 0xd9, 0x02, 0x71, 0x02, 0x39, 0x00, 0x59, 0x00, 0x59, 0x02, 0x39,
0x02, 0x6b, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x40
};
const byte scp_320x240x16_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, 0xb2, 0x00, 0x1e,
0x01, 0xe0, 0x00, 0x03, 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, 0xac, 0x00, 0x8d,
0x00, 0x97, 0x04, 0x19, 0x03, 0xfd, 0x00, 0x3f, 0x00, 0x3d, 0x03, 0xfd,
0x04, 0x15, 0x02, 0x00, 0x01, 0x86, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05,
0x01, 0x40
};
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
};
const byte scp_640x480x16_rgb[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x01, 0x36, 0x34, 0x30, 0x2a,
0x34, 0x38, 0x30, 0x2c, 0x20, 0x54, 0x72, 0x75, 0x65, 0x20, 0x43, 0x6f,
0x6c, 0x6f, 0x72, 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, 0xa9, 0xc1, 0x08, 0x00, 0xc3, 0x80, 0xd4,
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, 0x03, 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, 0x32, 0x00, 0xb2, 0x00, 0x81, 0x01, 0x32,
0x01, 0xb3, 0x02, 0x70, 0x02, 0x39, 0x00, 0x59, 0x00, 0x58, 0x02, 0x38,
0x02, 0x6b, 0x02, 0x00, 0x01, 0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06,
0x02, 0x80
};
const byte scp_640x480x16_vga[] = {
0x53, 0x43, 0x50, 0x4e, 0x00, 0x09, 0x00, 0x02, 0x36, 0x34, 0x30, 0x2a,
0x34, 0x38, 0x30, 0x2c, 0x20, 0x54, 0x72, 0x75, 0x65, 0x20, 0x43, 0x6f,
0x6c, 0x6f, 0x72, 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, 0x03, 0xc1, 0x00, 0x00, 0x01, 0x93, 0x00, 0x1f,
0x01, 0xe0, 0x00, 0x03, 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, 0xb5, 0x00, 0x8e,
0x00, 0x97, 0x04, 0x19, 0x03, 0xff, 0x00, 0x3f, 0x00, 0x3f, 0x03, 0xff,
0x04, 0x15, 0x02, 0x00, 0x01, 0x86, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08,
0x02, 0x80
};

View File

@ -0,0 +1,47 @@
/* 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_320x240x16_rgb[SCP_SIZE];
extern const byte scp_320x240x16_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];
extern const byte scp_640x480x16_rgb[SCP_SIZE];
extern const byte scp_640x480x16_vga[SCP_SIZE];
#endif

View File

@ -0,0 +1,221 @@
/* 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/mixer/atari/atari-mixer.h"
#include <math.h>
#include <mint/falcon.h>
#include "common/config-manager.h"
#include "common/debug.h"
#define DEFAULT_OUTPUT_RATE 24585
AtariMixerManager::AtariMixerManager() : MixerManager() {
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("output_samples", (int)_samples);
int samples = ConfMan.getInt("output_samples");
if (samples > 0)
_samples = samples;
ConfMan.setInt("output_samples", (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() {
g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
Buffoper(0x00);
Mfree(_atariSampleBuffer);
_atariSampleBuffer = _atariPhysicalSampleBuffer = _atariLogicalSampleBuffer = nullptr;
Sndstatus(SND_RESET);
Unlocksnd();
_atariInitialized = false;
delete[] _samplesBuf;
}
void AtariMixerManager::init() {
_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;
}
void AtariMixerManager::suspendAudio() {
debug("suspendAudio");
Buffoper(0x00);
_audioSuspended = true;
}
int AtariMixerManager::resumeAudio() {
debug("resumeAudio 1");
if (!_audioSuspended || !_atariInitialized) {
return -2;
}
debug("resumeAudio 2");
Buffoper(SB_PLA_ENA | SB_PLA_RPT);
_audioSuspended = false;
return 0;
}
bool AtariMixerManager::notifyEvent(const Common::Event &event) {
switch (event.type) {
case Common::EVENT_QUIT:
case Common::EVENT_RETURN_TO_LAUNCHER:
debug("silencing the mixer");
memset(_atariSampleBuffer, 0, 2 * _atariSampleBufferSize);
return false;
case Common::EVENT_MUTE:
_muted = !_muted;
debug("audio %s", _muted ? "off" : "on");
return false;
default:
[[fallthrough]];
}
return false;
}
void AtariMixerManager::update() {
if (_audioSuspended && !_muted) {
return;
}
static bool loadSampleFlag = true;
byte *buf = nullptr;
SndBufPtr sPtr;
if (Buffptr(&sPtr) != 0)
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) {
assert(_mixer);
// generates stereo 16-bit samples
int processed = _mixer->mixCallback(_samplesBuf, _samples * 4);
if (processed > 0) {
memcpy(buf, _samplesBuf, processed * 4);
} else {
memset(buf, 0, _atariSampleBufferSize);
}
}
}

View File

@ -0,0 +1,60 @@
/* 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_MIXER_ATARI_H
#define BACKENDS_MIXER_ATARI_H
#include "backends/mixer/mixer.h"
#include "common/events.h"
/**
* Atari XBIOS based audio mixer.
*/
class AtariMixerManager : public MixerManager, Common::EventObserver {
public:
AtariMixerManager();
virtual ~AtariMixerManager();
virtual void init() override;
void update();
void suspendAudio() override;
int resumeAudio() override;
bool notifyEvent(const Common::Event &event) override;
private:
int _clk;
uint32 _outputRate;
uint32 _samples;
uint8 *_samplesBuf;
bool _atariInitialized = false;
byte *_atariSampleBuffer = nullptr;
byte *_atariPhysicalSampleBuffer = nullptr;
byte *_atariLogicalSampleBuffer = nullptr;
size_t _atariSampleBufferSize; // one buffer (logical/physical)
bool _muted = false;
};
#endif

View File

@ -321,6 +321,15 @@ MODULE_OBJS += \
plugins/3ds/3ds-provider.o
endif
ifeq ($(BACKEND),atari)
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
ifeq ($(BACKEND),ds)
MODULE_OBJS += \
events/ds/ds-events.o \

View File

@ -0,0 +1,660 @@
/* 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 <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <mint/cookie.h>
#include <mint/falcon.h>
#include <mint/osbind.h>
// We use some stdio.h functionality here thus we need to allow some
// symbols. Alternatively, we could simply allow everything by defining
// FORBIDDEN_SYMBOL_ALLOW_ALL
#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
#include "common/scummsys.h"
#if defined(ATARI)
#include "backends/graphics/atari/atari-graphics-asm.h"
#include "backends/keymapper/hardware-input.h"
#include "backends/modular-backend.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/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-supervidel.h"
#include "backends/graphics/atari/atari-graphics-videl.h"
#include "common/hashmap.h"
#include "gui/debugger.h"
/*
* Include header files needed for the getFilesystemFactory() method.
*/
#include "backends/fs/posix/posix-fs-factory.h"
class OSystem_Atari : public ModularMixerBackend, public ModularGraphicsBackend, Common::EventSource {
public:
OSystem_Atari();
virtual ~OSystem_Atari();
void initBackend() override;
bool pollEvent(Common::Event &event) override;
Common::MutexInternal *createMutex() override;
uint32 getMillis(bool skipRecord = false) override;
void delayMillis(uint msecs) override;
void getTimeAndDate(TimeDate &td, bool skipRecord = false) const override;
Common::KeymapArray getGlobalKeymaps() override;
Common::HardwareInputSet *getHardwareInputSet() override;
void quit() override;
void logMessage(LogMessageType::Type type, const char *message) override;
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority) override;
Common::String getDefaultConfigFileName() override;
private:
AtariGraphicsManager *_atariGraphicsManager;
clock_t _startTime;
bool _video_initialized = false;
bool _ikbd_initialized = false;
bool _oldLmbDown = false;
bool _oldRmbDown = false;
bool _lshiftActive = false;
bool _rshiftActive = false;
bool _ctrlActive = false;
bool _altActive = false;
bool _capslockActive = false;
byte _unshiftToAscii[128];
byte _shiftToAscii[128];
byte _capsToAscii[128];
const Common::KeyCode _asciiToKeycode[128 - 32 - 1] = {
Common::KEYCODE_SPACE,
Common::KEYCODE_EXCLAIM,
Common::KEYCODE_QUOTEDBL,
Common::KEYCODE_HASH,
Common::KEYCODE_DOLLAR,
Common::KEYCODE_PERCENT,
Common::KEYCODE_AMPERSAND,
Common::KEYCODE_QUOTE,
Common::KEYCODE_LEFTPAREN,
Common::KEYCODE_RIGHTPAREN,
Common::KEYCODE_ASTERISK,
Common::KEYCODE_PLUS,
Common::KEYCODE_COMMA,
Common::KEYCODE_MINUS,
Common::KEYCODE_PERIOD,
Common::KEYCODE_SLASH,
Common::KEYCODE_0,
Common::KEYCODE_1,
Common::KEYCODE_2,
Common::KEYCODE_3,
Common::KEYCODE_4,
Common::KEYCODE_5,
Common::KEYCODE_6,
Common::KEYCODE_7,
Common::KEYCODE_8,
Common::KEYCODE_9,
Common::KEYCODE_COLON,
Common::KEYCODE_SEMICOLON,
Common::KEYCODE_LESS,
Common::KEYCODE_EQUALS,
Common::KEYCODE_GREATER,
Common::KEYCODE_QUESTION,
Common::KEYCODE_AT,
Common::KEYCODE_a,
Common::KEYCODE_b,
Common::KEYCODE_c,
Common::KEYCODE_d,
Common::KEYCODE_e,
Common::KEYCODE_f,
Common::KEYCODE_g,
Common::KEYCODE_h,
Common::KEYCODE_i,
Common::KEYCODE_j,
Common::KEYCODE_k,
Common::KEYCODE_l,
Common::KEYCODE_m,
Common::KEYCODE_n,
Common::KEYCODE_o,
Common::KEYCODE_p,
Common::KEYCODE_q,
Common::KEYCODE_r,
Common::KEYCODE_s,
Common::KEYCODE_t,
Common::KEYCODE_u,
Common::KEYCODE_v,
Common::KEYCODE_w,
Common::KEYCODE_x,
Common::KEYCODE_y,
Common::KEYCODE_z,
Common::KEYCODE_LEFTBRACKET,
Common::KEYCODE_BACKSLASH,
Common::KEYCODE_RIGHTBRACKET,
Common::KEYCODE_CARET,
Common::KEYCODE_UNDERSCORE,
Common::KEYCODE_BACKQUOTE,
Common::KEYCODE_a,
Common::KEYCODE_b,
Common::KEYCODE_c,
Common::KEYCODE_d,
Common::KEYCODE_e,
Common::KEYCODE_f,
Common::KEYCODE_g,
Common::KEYCODE_h,
Common::KEYCODE_i,
Common::KEYCODE_j,
Common::KEYCODE_k,
Common::KEYCODE_l,
Common::KEYCODE_m,
Common::KEYCODE_n,
Common::KEYCODE_o,
Common::KEYCODE_p,
Common::KEYCODE_q,
Common::KEYCODE_r,
Common::KEYCODE_s,
Common::KEYCODE_t,
Common::KEYCODE_u,
Common::KEYCODE_v,
Common::KEYCODE_w,
Common::KEYCODE_x,
Common::KEYCODE_y,
Common::KEYCODE_z,
Common::KEYCODE_INVALID, // {
Common::KEYCODE_INVALID, // |
Common::KEYCODE_INVALID, // }
Common::KEYCODE_TILDE
};
Common::HashMap<byte, Common::KeyCode> _scancodeToKeycode;
};
extern "C" void atari_ikbd_init();
extern "C" void atari_ikbd_shutdown();
extern void nf_init(void);
extern void nf_print(const char* msg);
OSystem_Atari::OSystem_Atari() {
_fsFactory = new POSIXFilesystemFactory();
_scancodeToKeycode[0x01] = Common::KEYCODE_ESCAPE;
_scancodeToKeycode[0x0e] = Common::KEYCODE_BACKSPACE;
_scancodeToKeycode[0x0f] = Common::KEYCODE_TAB;
_scancodeToKeycode[0x1c] = Common::KEYCODE_RETURN;
_scancodeToKeycode[0x39] = Common::KEYCODE_SPACE;
_scancodeToKeycode[0x3b] = Common::KEYCODE_F1;
_scancodeToKeycode[0x3c] = Common::KEYCODE_F2;
_scancodeToKeycode[0x3d] = Common::KEYCODE_F3;
_scancodeToKeycode[0x3e] = Common::KEYCODE_F4;
_scancodeToKeycode[0x3f] = Common::KEYCODE_F5;
_scancodeToKeycode[0x40] = Common::KEYCODE_F6;
_scancodeToKeycode[0x41] = Common::KEYCODE_F7;
_scancodeToKeycode[0x42] = Common::KEYCODE_F8;
_scancodeToKeycode[0x43] = Common::KEYCODE_F9;
_scancodeToKeycode[0x44] = Common::KEYCODE_F10;
_scancodeToKeycode[0x45] = Common::KEYCODE_PAGEUP; // Eiffel only
_scancodeToKeycode[0x46] = Common::KEYCODE_PAGEDOWN; // Eiffel only
_scancodeToKeycode[0x47] = Common::KEYCODE_HOME;
_scancodeToKeycode[0x48] = Common::KEYCODE_UP;
_scancodeToKeycode[0x4a] = Common::KEYCODE_KP_MINUS;
_scancodeToKeycode[0x4b] = Common::KEYCODE_LEFT;
_scancodeToKeycode[0x4c] = Common::KEYCODE_LMETA;
_scancodeToKeycode[0x4d] = Common::KEYCODE_RIGHT;
_scancodeToKeycode[0x4e] = Common::KEYCODE_KP_PLUS;
_scancodeToKeycode[0x4f] = Common::KEYCODE_PAUSE; // Eiffel only
_scancodeToKeycode[0x50] = Common::KEYCODE_DOWN;
_scancodeToKeycode[0x52] = Common::KEYCODE_INSERT;
_scancodeToKeycode[0x53] = Common::KEYCODE_DELETE;
_scancodeToKeycode[0x55] = Common::KEYCODE_END; // Eiffel only
_scancodeToKeycode[0x5b] = Common::KEYCODE_TILDE; // Eiffel only
_scancodeToKeycode[0x61] = Common::KEYCODE_F12; // UNDO
_scancodeToKeycode[0x62] = Common::KEYCODE_F11; // HELP
_scancodeToKeycode[0x63] = Common::KEYCODE_SLASH; // KEYPAD /
_scancodeToKeycode[0x64] = Common::KEYCODE_KP_DIVIDE;
_scancodeToKeycode[0x65] = Common::KEYCODE_KP_MULTIPLY;
_scancodeToKeycode[0x66] = Common::KEYCODE_KP_MULTIPLY; // duplicate?
_scancodeToKeycode[0x67] = Common::KEYCODE_7; // KEYPAD 7
_scancodeToKeycode[0x68] = Common::KEYCODE_8; // KEYPAD 8
_scancodeToKeycode[0x69] = Common::KEYCODE_9; // KEYPAD 9
_scancodeToKeycode[0x6a] = Common::KEYCODE_4; // KEYPAD 4
_scancodeToKeycode[0x6b] = Common::KEYCODE_5; // KEYPAD 5
_scancodeToKeycode[0x6c] = Common::KEYCODE_6; // KEYPAD 6
_scancodeToKeycode[0x6d] = Common::KEYCODE_1; // KEYPAD 1
_scancodeToKeycode[0x6e] = Common::KEYCODE_2; // KEYPAD 2
_scancodeToKeycode[0x6f] = Common::KEYCODE_3; // KEYPAD 3
_scancodeToKeycode[0x70] = Common::KEYCODE_0; // KEYPAD 0
_scancodeToKeycode[0x71] = Common::KEYCODE_KP_PERIOD;
_scancodeToKeycode[0x72] = Common::KEYCODE_KP_ENTER;
}
OSystem_Atari::~OSystem_Atari() {
debug("OSystem_Atari::~OSystem_Atari()");
if (_video_initialized) {
Supexec(asm_screen_falcon_restore);
_video_initialized = false;
}
if (_ikbd_initialized) {
Supexec(atari_ikbd_shutdown);
_ikbd_initialized = false;
}
}
static void ikbd_and_video_restore() {
Supexec(asm_screen_falcon_restore);
Supexec(atari_ikbd_shutdown);
}
void OSystem_Atari::initBackend() {
enum {
MCH_ST = 0,
MCH_STE,
MCH_TT,
MCH_FALCON,
MCH_CLONE,
MCH_ARANYM
};
long mch = MCH_ST<<16;
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) {
logMessage(LogMessageType::kError, "Disable fVDI, ScummVM accesses Videl directly\n");
quit();
}
nf_init();
_startTime = clock();
bool superVidel = VgetMonitor() == MON_VGA && Getcookie(C_SupV, NULL) == C_FOUND;
_timerManager = new DefaultTimerManager();
_eventManager = new DefaultEventManager(makeKeyboardRepeatingEventSource(this));
_savefileManager = new DefaultSaveFileManager();
if (superVidel)
_atariGraphicsManager = new AtariSuperVidelManager();
else
_atariGraphicsManager = new AtariVidelManager();
_graphicsManager = _atariGraphicsManager;
_mixerManager = new AtariMixerManager();
// Setup and start mixer
_mixerManager->init();
_KEYTAB *pKeyTables = (_KEYTAB*)Keytbl(KT_NOCHANGE, KT_NOCHANGE, KT_NOCHANGE);
memcpy(_unshiftToAscii, pKeyTables->unshift, 128);
memcpy(_shiftToAscii, pKeyTables->shift, 128);
memcpy(_capsToAscii, pKeyTables->caps, 128);
Supexec(atari_ikbd_init);
_ikbd_initialized = true;
Supexec(asm_screen_falcon_save);
_video_initialized = true;
Setexc(VEC_PROCTERM, ikbd_and_video_restore);
BaseBackend::initBackend();
}
//! bit 0: rmb
//! bit 1: lmb
volatile uint8 g_atari_ikbd_mouse_buttons_state = 0;
volatile int16 g_atari_ikbd_mouse_delta_x = 0;
volatile int16 g_atari_ikbd_mouse_delta_y = 0;
#define SCANCODES_SIZE 256
volatile uint8 g_atari_ikbd_scancodes[SCANCODES_SIZE];
uint16 g_atari_ikbd_scancodes_mask = SCANCODES_SIZE-1;
volatile uint16 g_atari_ikbb_scancodes_head = 0;
static uint16 g_atari_ikbb_scancodes_tail = 0;
bool OSystem_Atari::pollEvent(Common::Event &event) {
{
static uint32 startMillis = getMillis();
static uint32 oldMillis = getMillis();
uint32 curMillis = getMillis();
uint32 diff = curMillis - oldMillis;
oldMillis = curMillis;
if (diff > 0) {
static float avgFpsSum;
static int avgFpsCount;
avgFpsSum += 1000.0f / diff;
avgFpsCount++;
if (curMillis - startMillis >= 1000) {
float avgFps = avgFpsSum / avgFpsCount;
debug("*** Average FPS in 1s: %f ***", avgFps);
startMillis = curMillis;
avgFpsSum = 0;
avgFpsCount = 0;
}
}
}
((DefaultTimerManager *)_timerManager)->checkTimers();
((AtariMixerManager *)_mixerManager)->update();
if ((g_atari_ikbd_mouse_buttons_state & 0x01) && !_oldRmbDown) {
event.type = Common::EVENT_RBUTTONDOWN;
event.mouse = _atariGraphicsManager->getMousePosition();
_oldRmbDown = true;
return true;
}
if (!(g_atari_ikbd_mouse_buttons_state & 0x01) && _oldRmbDown) {
event.type = Common::EVENT_RBUTTONUP;
event.mouse = _atariGraphicsManager->getMousePosition();
_oldRmbDown = false;
return true;
}
if ((g_atari_ikbd_mouse_buttons_state & 0x02) && !_oldLmbDown) {
event.type = Common::EVENT_LBUTTONDOWN;
event.mouse = _atariGraphicsManager->getMousePosition();
_oldLmbDown = true;
return true;
}
if (!(g_atari_ikbd_mouse_buttons_state & 0x02) && _oldLmbDown) {
event.type = Common::EVENT_LBUTTONUP;
event.mouse = _atariGraphicsManager->getMousePosition();
_oldLmbDown = false;
return true;
}
if (g_atari_ikbd_mouse_delta_x != 0 || g_atari_ikbd_mouse_delta_y != 0) {
const int deltaX = g_atari_ikbd_mouse_delta_x;
const int deltaY = g_atari_ikbd_mouse_delta_y;
g_atari_ikbd_mouse_delta_x = g_atari_ikbd_mouse_delta_y = 0;
_atariGraphicsManager->updateMousePosition(deltaX, deltaY);
event.type = Common::EVENT_MOUSEMOVE;
event.mouse = _atariGraphicsManager->getMousePosition();
event.relMouse = Common::Point(deltaX, deltaY);
return true;
}
if (g_atari_ikbb_scancodes_head != g_atari_ikbb_scancodes_tail) {
byte scancode = g_atari_ikbd_scancodes[g_atari_ikbb_scancodes_tail++];
g_atari_ikbb_scancodes_tail &= SCANCODES_SIZE-1;
bool pressed = !(scancode & 0x80);
scancode &= 0x7f;
if (scancode == 0x1d)
_ctrlActive = pressed;
if (scancode == 0x2a)
_lshiftActive = pressed;
if (scancode == 0x36)
_rshiftActive = pressed;
if (scancode == 0x38)
_altActive = pressed;
if (scancode == 0x3a && pressed)
_capslockActive = !_capslockActive;
// Eiffel only
if (scancode == 0x59) {
event.type = Common::EVENT_WHEELUP;
event.mouse = _atariGraphicsManager->getMousePosition();
return true;
}
// Eiffel only
if (scancode == 0x5a) {
event.type = Common::EVENT_WHEELDOWN;
event.mouse = _atariGraphicsManager->getMousePosition();
return true;
}
uint16 ascii;
if (_lshiftActive || _rshiftActive) {
ascii = _shiftToAscii[scancode];
} else if (_capslockActive) {
ascii = _capsToAscii[scancode];
} else {
ascii = _unshiftToAscii[scancode];
}
Common::KeyCode keycode = _scancodeToKeycode.getValOrDefault(scancode, Common::KEYCODE_INVALID);
switch (keycode) {
case Common::KEYCODE_BACKSPACE:
ascii = Common::ASCII_BACKSPACE;
break;
case Common::KEYCODE_TAB:
ascii = Common::ASCII_TAB;
break;
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
ascii = Common::ASCII_RETURN;
break;
case Common::KEYCODE_ESCAPE:
ascii = Common::ASCII_ESCAPE;
break;
case Common::KEYCODE_SPACE:
ascii = Common::ASCII_SPACE;
break;
case Common::KEYCODE_F1:
ascii = Common::ASCII_F1;
break;
case Common::KEYCODE_F2:
ascii = Common::ASCII_F2;
break;
case Common::KEYCODE_F3:
ascii = Common::ASCII_F3;
break;
case Common::KEYCODE_F4:
ascii = Common::ASCII_F4;
break;
case Common::KEYCODE_F5:
ascii = Common::ASCII_F5;
break;
case Common::KEYCODE_F6:
ascii = Common::ASCII_F6;
break;
case Common::KEYCODE_F7:
ascii = Common::ASCII_F7;
break;
case Common::KEYCODE_F8:
ascii = Common::ASCII_F8;
break;
case Common::KEYCODE_F9:
ascii = Common::ASCII_F9;
break;
case Common::KEYCODE_F10:
ascii = Common::ASCII_F10;
break;
case Common::KEYCODE_F11:
ascii = Common::ASCII_F11;
break;
case Common::KEYCODE_F12:
ascii = Common::ASCII_F12;
break;
default:
break;
}
if (ascii >= ' ' && ascii <= '~') {
if (keycode == Common::KEYCODE_INVALID)
keycode = _asciiToKeycode[ascii - ' '];
}
event.type = pressed ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP;
event.kbd = Common::KeyState(keycode, ascii);
event.kbd.flags |= _ctrlActive ? Common::KBD_CTRL : 0;
event.kbd.flags |= _altActive ? Common::KBD_ALT : 0;
event.kbd.flags |= (_lshiftActive || _rshiftActive) ? Common::KBD_SHIFT : 0;
event.kbd.flags |= _capslockActive ? Common::KBD_CAPS : 0;
return true;
}
return false;
}
Common::MutexInternal *OSystem_Atari::createMutex() {
return new NullMutexInternal();
}
uint32 OSystem_Atari::getMillis(bool skipRecord) {
// CLOCKS_PER_SEC is 200, so no need to use floats
return 1000 * (clock() - _startTime) / CLOCKS_PER_SEC;
}
void OSystem_Atari::delayMillis(uint msecs) {
usleep(msecs * 1000);
}
void OSystem_Atari::getTimeAndDate(TimeDate &td, bool skipRecord) const {
debug("getTimeAndDate");
time_t curTime = time(0);
// TODO: if too slow (e.g. when calling RandomSource::RandomSource()), rewrite
struct tm t = *localtime(&curTime);
td.tm_sec = t.tm_sec;
td.tm_min = t.tm_min;
td.tm_hour = t.tm_hour;
td.tm_mday = t.tm_mday;
td.tm_mon = t.tm_mon;
td.tm_year = t.tm_year;
td.tm_wday = t.tm_wday;
}
Common::KeymapArray OSystem_Atari::getGlobalKeymaps() {
Common::KeymapArray globalMaps = BaseBackend::getGlobalKeymaps();
Common::Keymap *keymap = _atariGraphicsManager->getKeymap();
globalMaps.push_back(keymap);
return globalMaps;
}
Common::HardwareInputSet *OSystem_Atari::getHardwareInputSet() {
Common::CompositeHardwareInputSet *inputSet = new Common::CompositeHardwareInputSet();
inputSet->addHardwareInputSet(new Common::MouseHardwareInputSet(Common::defaultMouseButtons));
inputSet->addHardwareInputSet(new Common::KeyboardHardwareInputSet(Common::defaultKeys, Common::defaultModifiers));
return inputSet;
}
void OSystem_Atari::quit() {
Common::String str = Common::String::format("OSystem_Atari::quit()\n");
logMessage(LogMessageType::kDebug, str.c_str());
g_system->destroy();
exit(0);
}
void OSystem_Atari::logMessage(LogMessageType::Type type, const char *message) {
FILE *output = 0;
if (type == LogMessageType::kInfo || type == LogMessageType::kDebug)
output = stdout;
else
output = stderr;
fputs(message, output);
fflush(output);
nf_print(message);
}
void OSystem_Atari::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
#ifdef DATA_PATH
// Add the global DATA_PATH to the directory search list
// See also OSystem_SDL::addSysArchivesToSearchSet()
Common::FSNode dataNode(DATA_PATH);
if (dataNode.exists() && dataNode.isDirectory()) {
s.add(DATA_PATH, new Common::FSDirectory(dataNode, 4), priority);
}
#endif
}
Common::String OSystem_Atari::getDefaultConfigFileName() {
const Common::String baseConfigName = OSystem::getDefaultConfigFileName();
Common::String configFile;
const char *envVar = getenv("HOME");
if (envVar && *envVar) {
configFile = envVar;
configFile += '/';
configFile += baseConfigName;
if (configFile.size() < MAXPATHLEN)
return configFile;
}
return baseConfigName;
}
OSystem *OSystem_Atari_create() {
return new OSystem_Atari();
}
int main(int argc, char *argv[]) {
g_system = OSystem_Atari_create();
assert(g_system);
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
g_system->destroy();
return res;
}
#endif

View File

@ -0,0 +1,233 @@
/* 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/>.
*
*/
/*
* IKBD 6301 interrupt routine
*
* Patrice Mandin
*/
.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
.text
_atari_ikbd_init:
| Disable interrupts
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
| g_atari_ikbd_scancodes[g_atari_ikbb_scancodes_head] = scancode
moveb d0,(0.b,a0,d1.w)
addql #1,d1
andw _g_atari_ikbd_scancodes_mask,d1
movew 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@-
rts
| Mouse packet, byte #2
ikbd_mousex:
moveml d0-d1/a0,sp@-
| 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
movel #ikbd_mousey,0x118:w
bras ikbd_endit_stack
| Mouse packet, byte #3
ikbd_mousey:
moveml d0-d1/a0,sp@-
| 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

View File

@ -0,0 +1,11 @@
MODULE := backends/platform/atari
MODULE_OBJS := \
atari.o \
atari_ikbd.o \
native_features.o
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
OBJS := $(MODULE_OBJS) $(OBJS)
MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))

View File

@ -0,0 +1,96 @@
/* 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/>.
*
*/
// Taken from mintlib (https://github.com/freemint/mintlib)
// (c) Thorsten Otto
#include <mint/osbind.h>
#include <stdint.h>
#define NATFEAT_ID 0x7300
#define NATFEAT_CALL 0x7301
#define ASM_NATFEAT3(opcode) "\t.word " #opcode "\n"
#define ASM_NATFEAT2(opcode) ASM_NATFEAT3(opcode)
#define ASM_NATFEAT(n) ASM_NATFEAT2(n)
static unsigned short const nf_id_opcodes[] = { NATFEAT_ID, 0x4e75 };
static unsigned short const nf_call_opcodes[] = { NATFEAT_CALL, 0x4e75 };
#define _nf_get_id(feature_name) ((long (__CDECL *)(const char *))nf_id_opcodes)(feature_name)
#define _nf_call(id, ...) ((long (__CDECL *)(long, ...))nf_call_opcodes)(id, __VA_ARGS__)
/*
* on ColdFire, the NATFEAT_ID opcode is actually
* "mvs.b d0,d1",
* which means the following code will NOT detect
* the presence of an emulator (should there ever
* be an emulator capable of emulating a ColdFire processor).
* Luckily, executing the code on a CF processor is still
* harmless since all it does is clobber D1.
*/
static long _nf_detect_tos(void) {
register long ret __asm__ ("d0");
register const char *nf_version __asm__("a1") = "NF_VERSION";
__asm__ volatile(
"\tmove.l %1,-(%%sp)\n"
"\tmoveq #0,%%d0\n" /* assume no NatFeats available */
"\tmove.l %%d0,-(%%sp)\n"
"\tlea (1f:w,%%pc),%%a1\n"
"\tmove.l (0x0010).w,%%a0\n" /* illegal instruction vector */
"\tmove.l %%a1,(0x0010).w\n"
"\tmove.l %%sp,%%a1\n" /* save the ssp */
"\tnop\n" /* flush pipelines (for 68040+) */
ASM_NATFEAT(NATFEAT_ID) /* Jump to NATFEAT_ID */
"\ttst.l %%d0\n"
"\tbeq.s 1f\n"
"\tmoveq #1,%%d0\n" /* NatFeats detected */
"\tmove.l %%d0,(%%sp)\n"
"1:\n"
"\tmove.l %%a1,%%sp\n"
"\tmove.l %%a0,(0x0010).w\n"
"\tmove.l (%%sp)+,%%d0\n"
"\taddq.l #4,%%sp\n" /* pop nf_version argument */
"\tnop\n" /* flush pipelines (for 68040+) */
: "=g"(ret) /* outputs */
: "g"(nf_version) /* inputs */
: __CLOBBER_RETURN("d0") "a0", "d1", "cc" AND_MEMORY
);
return ret;
}
static long nf_stderr_id;
void nf_init(void) {
long ret = Supexec(_nf_detect_tos);
if (ret == 1)
nf_stderr_id = _nf_get_id("NF_STDERR");
}
void nf_print(const char* msg) {
if (nf_stderr_id)
_nf_call(nf_stderr_id | 0, (uint32_t)msg);
}

View File

@ -0,0 +1,422 @@
ScummVM
=======
This is a new port of ScummVM (https://www.scummvm.org), a program which allows
you to run certain classic graphical adventure and role-playing games, provided
you already have their data files.
You can find a full list with details on which games are supported and how well
on the compatibility page: https://www.scummvm.org/compatibility.
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
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.)
but I have decided to take a different route:
- Reduced executable size, basically whatever is not essential or plausible on
our platform is left out. That reduces the file size to half. See also the
next point.
- Because there's a limited horsepower available on our platform, features like
hi-res 16bpp graphics, software synthesizers, scalers, real-time software
MP3/OGG/FLAC playback etc., are omitted. This saves memory and disk space,
making the whole port more lightweight.
- This port natively talks to the hardware, avoiding intermediate layers like
SDL. Thus, it has more optimisations, fewer redraws, fewer data copying and
is less crash-prone.
- Because we limit scope only to 8bpp games, it opens a door to more thorough
testing and there is a certain interest in this in the community. 16bpp games
could be played only in ARAnyM or similar, limiting the test audience a lot.
After I had seen how snappy NovaCoder's ScummVM on the Amiga is (who coded
his own backend), I decided to do the same and see whether I could do better.
And I could!
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).
- 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.
- Direct rendering and single/double/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@16bpp for
the overlay in RGB/SuperVidel, ...)
- Custom (hardware based) aspect ratio correction (!)
- Support for PC keys (page up, page down, pause, F11/F12, ...) and mouse wheel
(Eiffel/Aranym only)
- Still without any assembly optimizations...
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.
Platform-specific features outside the GUI
------------------------------------------
Keyboard shortcut "CONTROL+u": immediate mute on/off toggle (disables also
sample mixing, contrary to what "Mute all" in the options does!)
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).
"output_samples" 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 most
games on my CT60@66 MHz.
If you want to play with those two values, the rule of thumb is: (lag in ms) =
(output_samples / output_rate) * 1000. But it's totally OK just to double the
samples value to get rid of stuttering in a heavier game.
Graphics modes
--------------
This topic is more complex than it looks. ScummVM renders game graphics using
rectangles and this port offers following options to render them:
Direct rendering (vsync on/off) - present only with the SuperVidel
Single buffering (vsync on/off)
Double buffering (vsync always on, the checkbox is ignored)
Triple buffering (vsync always off, the checkbox just selects a different kind)
Direct rendering:
~~~~~~~~~~~~~~~~~
This is direct writing of the pixels into (SuperVidel's) screen buffer. Since
the updates are supplied as rectangles and not the whole screen there's no way
to implement direct writing *and* double/triple buffering. Vsync() only
synchronizes the point when the rendering process begins - if it takes more
than the time reserved for the vertical blank interrupt (what happens
with most of the games), you'll see screen tearing.
Pros:
- fastest possible rendering (especially in 640x480 with a lot of small
rectangle updates where the buffer copying drags performance down)
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.
SuperBlitter used: sometimes (when ScummVM allocates surface via its create()
function; custom/small buffers originating in the engine code are still copied
using the CPU).
Single buffering:
~~~~~~~~~~~~~~~~~
This is very similar to the previous mode with the difference that the engine
uses an intermediate buffer for storing the rectangles but yet it remembers
which ones they were. It works also on plain Videl and applies the chunky to
planar process to each one of the rectangles separately, avoiding fullscreen
updates (but if such is needed, there is an optimized code path for it). Vsync()
is used the same way as in the previous mode, i.e. screen tearing is still
possible.
Pros:
- second fastest possible rendering
- doesn't update the whole screen (works best with a moderate amount of
rectangles to update)
Cons:
- screen tearing in most cases
- if there are too many smaller rectangles, it can be less efficient than
updating the whole buffer at once
SuperBlitter used: yes, for rectangle blitting to screen and cursor restoration.
Sometimes also for generic copying between buffers (see above).
Double buffering:
~~~~~~~~~~~~~~~~~
The most common rendering mode. It extends the idea of single buffering - it
renders into two buffers, one is visible while the other one is used for
updating. At the end of the update process the two buffers are swapped, so the
newly updated one is displayed. By definition, Vsync() must be always enabled
(the buffers are swapped in the vertical blank handler) otherwise you'd see
screen tearing.
Pros:
- stable frame rate, leading to fixed e.g. 30 FPS rendering for the whole time
if game takes, say, 1.7 - 1.9 frames per update
- no screen tearing in any situation
Cons:
- since two buffers are present, the buffer is always blitted into the screen
surface as whole, even if only one tiny little rectangle is changed (excluding
the cursor)
- frame rate is set to 60/30/15/etc FPS so you can see big irregular jumps
between 30 and 15 FPS for example; this is happening when screen updates take
variable amount of time but since Vsync() is always called, the rendering
pipeline has to wait until the next frame even if only 1% of the frame time
has been used.
SuperBlitter used: yes, for rectangle blitting to screen and cursor restoration.
Sometimes also for generic copying between buffers (see above).
Triple buffering:
~~~~~~~~~~~~~~~~~
Best of both worlds - screen tearing is avoided thanks to using of multiple
buffers and the rendering pipeline doesn't have to wait until Vsync(). The vsync
flag is used only to differentiate between two (very similar) modes of
operation:
1. "True triple buffering" as described in
https://en.wikipedia.org/wiki/Multiple_buffering#Triple_buffering (vsync on)
2. "Swap chain" as described in https://en.wikipedia.org/wiki/Swap_chain (vsync
off)
Pros:
- best compromise between performance and visual experience
- works well with both higher and lower frame rates
Cons:
- since three buffers are present, the buffer is always blitted into the screen
surface as whole, even if only one tiny little rectangle is changed (excluding
the cursor)
- slightly irregular frame rate (depends solely on the game's complexity)
- in case of extremely fast rendering in 1.), one or more buffers are
dropped in favor of showing only the most recent one (unlikely)
- in case of extremely fast rendering in 2.), screen tearing is possible
because the rendering pipeline starts overwriting the buffer which is
currently displayed (unlikely)
SuperBlitter used: yes, for rectangle blitting to screen and cursor restoration.
Sometimes also for generic copying between buffers (see above).
Triple buffering with vsync on is the default mode for this port.
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
- 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
SuperBlitter copying)
- when SuperVidel FW version >= 9 is detected, the async FIFO buffer is used
instead of the slower sync blitting (where one has to wait for every
rectangle blit to finish). This applies only for chunky buffer -> screen
surfaces copy (as the generic surface copy can't rely on this behavior) but
despite this limitation it sometimes leads to nearly zero-cost rendering
and makes a *huge* difference for 640x480 fullscreen updates.
Performance considerations/pitfalls
-----------------------------------
It's important to understand what affects performance on our limited platform
to avoid unpleasant playing experiences.
Game engines with unexpected performance hit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A typical example from this category is the Gobliins engine (and its
sequels). At first it looks like our machine / backend is doing something
terribly wrong but the truth is it is the engine itself which is doing a lot of
unnecessary redraws and updates, sometimes even before reaching the backend.
The only real solution is to profile and fix the engine.
Too many fullscreen updates
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Somewhat related to the previous point - sometimes the engine authors didn't
realize the impact of every update on the overall performance and instead of
updating only the rectangles that really had changed, they ask for a full screen
update. Not a problem on a >1 GHz machine but very visible on Atari! Also, this
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
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 take down as many as 10 FPS.
CD music slows everything down
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some games use separate audio *and* video streams (files). Even if the CPU is
able to handle both, the bottleneck becomes ... disk access. This is visible in
The Curse Of Monkey Island for example -- there's audible stuttering during the
intro sequence (and during the game as well). Increasing "output_samples" makes
the rendering literally crawling! Why? Because disk I/O is busy with loading
even *more* sample data so there's less time for video loading and rendering.
Try to put "musdisk1.bun" and "musdisk2.bun" into a ramdisk (i.e. u:/ram in
FreeMiNT), you'll be pleasantly surprised with the performance boost gained.
"Mute" vs. "Mute all" in GUI vs. "No music" in GUI
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Not the same thing. "Mute" (available only via the shortcut CONTROL+u) generates
an event to which the sample mixer can react (i.e. stop mixing the silence...).
"Mute all" doesn't generate anything, it basically just lowers the volume of the
music to zero.
"No music" means using the null audio plugin which prevents generating any MIDI
music (and therefore avoiding the expensive synthesis emulation) but beware, it
doesn't affect CD (*.wav) playback at all!
So for the best performance, always choose "No music" in the GUI options when
the game contains MIDI tracks and "Mute" when the game contains a sampled
soundtrack.
Please note that it is not that bad, you surely can play The Secret of Monkey
Island with AdLib enabled (but the CD/talkie versions sound better and
are cheaper to play ;)).
Vsync in GUI
~~~~~~~~~~~~
Carefully with the vsync option. It can easily cripple direct/single buffer
rendering by 10-15 FPS if not used with caution. That happens if a game takes,
say, 1.2 frames per update (so causing screen tearing anyway and rendering the
option useless) but Vsync() forces it to wait 2 full frames instead.
By the way, the vsync flag in Global Options affects also the overlay rendering
(with all the pitfalls which apply to the single buffering mode)
Slow GUI
~~~~~~~~
Themes handling is quite slow - each theme must be depacked, each one contains
quite a few XML files to parse and quite a few images to load/convert. That's
the reason why the built-in one is used as default, it dramatically speeds up
loading time. A compromise solution is to depack the theme in an equally named
directory (i.e. avoiding the depacking phase) but you need a filesystem with
long name support for that to work.
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).
- 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).
And of course, don't forget to set the extra path in Game options to the
folder where *.wav files are located! For MI2 just use the DOS version,
there are no CD tracks available. :(
Future plans
------------
- aspect ratio correction for VGA/SuperVidel
- unified file paths in scummvm.ini
- 8bpp overlay (and get rid of all that 16bpp handling code)
- profiling :) (see also https://github.com/scummvm/scummvm/pull/2382)
- DSP-based sample mixer
- avoid loading music/speech files (and thus slowing down everything) if muted
- assembly copy routines for screen/chunky surfaces (even with SuperVidel
present it is not possible to use the SuperBlitter for every surface)
- cached audio/video streams (i.e. don't load only "output_samples" number of
samples but cache, say, 1 second so disk i/o wont be so stressed)
- using LDG or Thorsten Otto's sharedlibs: https://tho-otto.de/sharedlibs.php
for game engine plugins to relieve the huge binary size
- reuse modified rects in double/triple buffer in the next frame - that way we
wouldn't need to refresh the whole screen in every case
- add support for the TT030; this would be easily possible when I rewrite the
renderer with a more flexible resolution switching
- ignore (queue) updateScreen() calls to avoid aggressive drawing / buffer
switching from some engines; update every X ms instead
- 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)
Closing words
—------------
I have opened a pull request with all of my code
(https://github.com/scummvm/scummvm/pull/4687) so who knows, maybe ScummVM
2.8.0 for Atari will be already present on the official website. :-)
MiKRO / Mystic Bytes, XX.XX.2023
Kosice / Slovakia
miro.kropacek@gmail.com
http://mikro.atari.org

26
configure vendored
View File

@ -1637,6 +1637,11 @@ kos32)
_host_cpu=i686
_host_alias=kos32
;;
m68k-atari-mint)
_host_os=mint
_host_cpu=m68k
_host_alias=m68k-atari-mint
;;
maemo)
_host_os=maemo
_host_cpu=arm
@ -3553,6 +3558,17 @@ if test -n "$_host"; then
_port_mk="backends/platform/sdl/kolibrios/kolibrios.mk"
;;
m68k-atari-mint)
# auto -> yes
if test "$_debug_build" = "no"; then
# --disable-debug
append_var LDFLAGS "-s"
fi
# auto -> no
if test "$_optimizations" = "yes"; then
# --enable-release, --enable-optimizations
append_var CXXFLAGS "-fomit-frame-pointer"
fi
_seq_midi=no
_timidity=no
;;
@ -3841,6 +3857,16 @@ case $_backend in
_sdlnet=no
fi
;;
atari)
append_var DEFINES "-DATARI"
#append_var DEFINES "-DDISABLE_FANCY_THEMES"
#append_var DEFINES "-DDISABLE_SID"
#append_var DEFINES "-DDISABLE_NES_APU"
#append_var DEFINES "-DDISABLE_DOSBOX_OPL"
append_var ASFLAGS "-m68030"
append_var CXXFLAGS "-m68020-60"
append_var LDFLAGS "-m68020-60"
;;
dc)
append_var INCLUDES '-I$(srcdir)/backends/platform/dc'
append_var INCLUDES "-isystem $RONINDIR/include"