scummvm/backends/platform/dc/dcutils.cpp
2021-12-26 18:48:43 +01:00

251 lines
5.7 KiB
C++

/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_chdir
#include "dc.h"
#include "dcutils.h"
#include <ronin/gddrive.h>
int getCdState()
{
unsigned int param[4];
gdGdcGetDrvStat(param);
return param[0];
}
extern "C" {
int dummy_cdfs_get_volume_id(char *, unsigned int) {
return -1;
}
int cdfs_get_volume_id(char *, unsigned int) __attribute__ ((weak, alias ("dummy_cdfs_get_volume_id")));
}
DiscLabel::DiscLabel() {
if (cdfs_get_volume_id(buf, 32) < 0)
memset(buf, '*', 32);
}
bool DiscLabel::operator==(const DiscLabel &other) const {
return !memcmp(buf, other.buf, 32);
}
void DiscLabel::get(char *p) const {
memcpy(p, buf, 32);
p[32] = 0;
}
void draw_solid_quad(float x1, float y1, float x2, float y2,
int c0, int c1, int c2, int c3)
{
struct polygon_list mypoly;
struct packed_colour_vertex_list myvertex;
mypoly.cmd =
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_OPAQUE|TA_CMD_POLYGON_SUBLIST|
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|
TA_CMD_POLYGON_GOURAUD_SHADING;
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
mypoly.mode2 =
TA_POLYMODE2_BLEND_SRC|TA_POLYMODE2_FOG_DISABLED;
mypoly.texture = 0;
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
ta_commit_list(&mypoly);
myvertex.cmd = TA_CMD_VERTEX;
myvertex.ocolour = 0;
myvertex.z = 0.5;
myvertex.u = 0.0;
myvertex.v = 0.0;
myvertex.colour = c0;
myvertex.x = x1;
myvertex.y = y1;
ta_commit_list(&myvertex);
myvertex.colour = c1;
myvertex.x = x2;
ta_commit_list(&myvertex);
myvertex.colour = c2;
myvertex.x = x1;
myvertex.y = y2;
ta_commit_list(&myvertex);
myvertex.colour = c3;
myvertex.x = x2;
myvertex.cmd |= TA_CMD_VERTEX_EOS;
ta_commit_list(&myvertex);
}
void draw_trans_quad(float x1, float y1, float x2, float y2,
int c0, int c1, int c2, int c3)
{
struct polygon_list mypoly;
struct packed_colour_vertex_list myvertex;
mypoly.cmd =
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_TRANSPARENT|TA_CMD_POLYGON_SUBLIST|
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|
TA_CMD_POLYGON_GOURAUD_SHADING;
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
mypoly.mode2 =
TA_POLYMODE2_BLEND_SRC_ALPHA|TA_POLYMODE2_BLEND_DST_INVALPHA|
TA_POLYMODE2_FOG_DISABLED|TA_POLYMODE2_ENABLE_ALPHA;
mypoly.texture = 0;
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
ta_commit_list(&mypoly);
myvertex.cmd = TA_CMD_VERTEX;
myvertex.ocolour = 0;
myvertex.z = 0.5;
myvertex.u = 0.0;
myvertex.v = 0.0;
myvertex.colour = c0;
myvertex.x = x1;
myvertex.y = y1;
ta_commit_list(&myvertex);
myvertex.colour = c1;
myvertex.x = x2;
ta_commit_list(&myvertex);
myvertex.colour = c2;
myvertex.x = x1;
myvertex.y = y2;
ta_commit_list(&myvertex);
myvertex.colour = c3;
myvertex.x = x2;
myvertex.cmd |= TA_CMD_VERTEX_EOS;
ta_commit_list(&myvertex);
}
DiscSwap::DiscSwap(const char *label, unsigned int argb_) : argb(argb_) {
x = 320 - 7 * strlen(label);
lab.create_texture(label);
}
void DiscSwap::run()
{
int wasopen = 0;
for (;;) {
int s = getCdState();
if (s >= 6)
wasopen = 1;
if (s > 0 && s < 6 && wasopen) {
cdfs_reinit();
chdir("/"); // Expect this one to fail with ERR_DISKCHG
chdir("/"); // but this one to succeed
return;
}
ta_begin_frame();
background();
ta_commit_end();
lab.draw(x, 200.0, argb);
ta_commit_frame();
interact();
}
}
namespace DC_Flash {
static int syscall_info_flash(int sect, int *info)
{
return (*(int (**)(int, void*, int, int))0x8c0000b8)(sect,info,0,0);
}
static int syscall_read_flash(int offs, void *buf, int cnt)
{
return (*(int (**)(int, void*, int, int))0x8c0000b8)(offs,buf,cnt,1);
}
static int flash_crc(const char *buf, int size)
{
int i, c, n = -1;
for(i=0; i<size; i++) {
n ^= (buf[i]<<8);
for(c=0; c<8; c++)
if(n & 0x8000)
n = (n << 1) ^ 4129;
else
n <<= 1;
}
return (unsigned short)~n;
}
int flash_read_sector(int partition, int sec, unsigned char *dst)
{
int s, r, n, b, bmb, got=0;
int info[2];
char buf[64];
char bm[64];
if((r = syscall_info_flash(partition, info))<0)
return r;
if((r = syscall_read_flash(info[0], buf, 64))<0)
return r;
if(memcmp(buf, "KATANA_FLASH", 12) ||
buf[16] != partition || buf[17] != 0)
return -2;
n = (info[1]>>6)-1-((info[1] + 0x7fff)>>15);
bmb = n+1;
for(b = 0; b < n; b++) {
if(!(b&511)) {
if((r = syscall_read_flash(info[0] + (bmb++ << 6), bm, 64))<0)
return r;
}
if(!(bm[(b>>3)&63] & (0x80>>(b&7)))) {
if((r = syscall_read_flash(info[0] + ((b+1) << 6), buf, 64))<0)
return r;
else if((s=READ_LE_UINT16(buf+0)) == sec &&
flash_crc(buf, 62) == READ_LE_UINT16(buf+62)) {
memcpy(dst+(s-sec)*60, buf+2, 60);
got=1;
}
}
}
return got;
}
int get_locale_setting()
{
unsigned char data[60];
if (flash_read_sector(2,5,data) == 1)
return data[5];
else
return -1;
}
} // End of namespace DC_Flash