1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-01-17 12:58:50 +01:00

#407 32X support, initial commit, cinematic cutscenes

This commit is contained in:
XProger 2022-02-24 02:10:05 +03:00
parent 28ac8e9ba7
commit fe8826d5b8
21 changed files with 4251 additions and 55 deletions

View File

@ -13,6 +13,69 @@
#define CAM_ANGLE_COMBAT ANGLE(-10)
#define CAM_ANGLE_MAX ANGLE(85)
void Camera::initCinematic()
{
switch (gLevelID)
{
case LVL_TR1_CUT_1:
gCinematicCamera.view.pos.x = 36668;
gCinematicCamera.view.pos.z = 63180;
gCinematicCamera.targetAngle.y = -ANGLE(128);
break;
case LVL_TR1_CUT_2:
gCinematicCamera.view.pos.x = 51962;
gCinematicCamera.view.pos.z = 53760;
gCinematicCamera.targetAngle.y = ANGLE_90 - 4;
break;
case LVL_TR1_CUT_3:
gCinematicCamera.targetAngle.y = ANGLE_90;
//level.flip();
break;
case LVL_TR1_CUT_4:
gCinematicCamera.targetAngle.y = ANGLE_90;
break;
default:
ASSERT(false);
break;
}
}
void Camera::updateCinematic()
{
const CameraFrame &frame = level.cameraFrames[timer++];
int32 px = frame.pos.x;
int32 py = frame.pos.y;
int32 pz = frame.pos.z;
int32 dx = frame.target.x - px;
int32 dy = frame.target.y - py;
int32 dz = frame.target.z - pz;
anglesFromVector(dx, dy, dz, angle.x, angle.y);
int32 s, c;
sincos(targetAngle.y, s, c);
X_ROTXY(pz, px, s, c);
px += view.pos.x;
py += view.pos.y;
pz += view.pos.z;
matrixSetView(_vec3i(px, py, pz), angle.x, angle.y + targetAngle.y);
Room* nextRoom = view.room->getRoom(px, py, pz);
if (nextRoom) {
view.room = nextRoom;
}
if (timer >= level.cameraFramesCount) {
timer = level.cameraFramesCount - 1;
nextLevel(LevelID(gLevelID + 1));
}
}
void Camera::init(ItemObj* lara)
{
ASSERT(lara->extraL);

View File

@ -7,7 +7,7 @@ vec3i gCameraViewPos;
Matrix gMatrixStack[MAX_MATRICES];
Matrix* gMatrixPtr = gMatrixStack;
EWRAM_DATA Sphere gSpheres[2][MAX_SPHERES];
EWRAM_DATA Sphere gSpheres[2][MAX_SPHERES]; // EWRAM 1k
const FloorData* gLastFloorData;
FloorData gLastFloorSlant;
@ -45,7 +45,7 @@ EWRAM_DATA ExtraInfoLara playersExtra[MAX_PLAYERS];
#ifdef __3DO__ // TODO fix the title scren on 3DO
EWRAM_DATA LevelID gLevelID = LVL_TR1_1;
#else
EWRAM_DATA LevelID gLevelID = LVL_TR1_TITLE;
EWRAM_DATA LevelID gLevelID = LVL_TR1_1;
#endif
const LevelInfo gLevelInfo[LVL_MAX] = {
@ -1144,7 +1144,7 @@ X_INLINE int16 lerpAngleSlow(int16 a, int16 b, int32 mul, int32 div)
void matrixPush_c()
{
ASSERT(gMatrixPtr - gMatrixStack < MAX_MATRICES);
memcpy(gMatrixPtr + 1, gMatrixPtr, sizeof(Matrix));
gMatrixPtr[1] = gMatrixPtr[0];
gMatrixPtr++;
}
@ -1556,7 +1556,8 @@ void palSet(const uint16* palette, int32 gamma, int32 bright)
if (gamma || bright)
{
uint16 tmp[256];
uint16* tmp = (uint16*)&gSpheres;
if (gamma) {
palGamma(pal, tmp, gamma);
pal = tmp;
@ -1574,9 +1575,11 @@ void palSet(const uint16* palette, int32 gamma, int32 bright)
void dmaFill(void* dst, uint8 value, uint32 count)
{
ASSERT((count & 3) == 0);
#ifdef __GBA__
#if defined(__GBA__)
vu32 v = value;
dma3_fill(dst, v, count);
#elif defined(__32X__)
fast_memset(dst, value, count >> 2);
#else
memset(dst, value, count);
#endif
@ -1586,8 +1589,10 @@ void dmaFill(void* dst, uint8 value, uint32 count)
void dmaCopy(const void* src, void* dst, uint32 size)
{
ASSERT((size & 3) == 0);
#ifdef __GBA__
#if defined(__GBA__)
dma3_cpy(dst, src, size);
#elif defined(__32X__)
fast_memcpy(dst, src, size >> 2);
#else
memcpy(dst, src, size);
#endif

View File

@ -10,46 +10,64 @@
#if defined(_WIN32)
#define MODE4
//#define MODE13
#define USE_DIV_TABLE
#define MODE4
#define FRAME_WIDTH 240
#define FRAME_HEIGHT 160
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#elif defined(__GBA__)
#define MODE4
#define USE_DIV_TABLE
#define ROM_READ
#define USE_ASM
#define ALIGNED_LIGHTMAP
#define MODE4
#define FRAME_WIDTH 240
#define FRAME_HEIGHT 160
#include <tonc.h>
#elif defined(__NDS__)
#define MODEHW
#define USE_DIV_TABLE
#define MODEHW
#define FRAME_WIDTH 256
#define FRAME_HEIGHT 192
#include <nds.h>
#include <fat.h>
#include <filesystem.h>
#elif defined(__TNS__)
#define MODE13
#define USE_DIV_TABLE
#define MODE13
#define FRAME_WIDTH 320
#define FRAME_HEIGHT 240
#include <os.h>
#elif defined(__DOS__)
#define MODE13
#define USE_DIV_TABLE
#define MODE13
#define FRAME_WIDTH 320
#define FRAME_HEIGHT 200
#include <stdlib.h>
#include <stddef.h>
#include <conio.h>
#include <dos.h>
#include <mem.h>
#elif defined(__3DO__)
#define MODEHW
#define USE_DIV_TABLE // 4k of DRAM
#define CPU_BIG_ENDIAN
#define USE_ASM
#define MODEHW
#define FRAME_WIDTH 320
#define FRAME_HEIGHT 240
#include <displayutils.h>
#include <debug.h>
#include <nodes.h>
@ -69,6 +87,16 @@
#include <celutils.h>
#include <timerutils.h>
#include <hardware.h>
#elif defined(__32X__)
#define USE_DIV_TABLE
#define CPU_BIG_ENDIAN
#define ROM_READ
#define MODE13
#define FRAME_WIDTH 320
#define FRAME_HEIGHT 224
#include "32x.h"
#else
#error unsupported platform
#endif
@ -81,30 +109,8 @@
#include <math.h>
#include <limits.h>
#include <new>
#if defined(MODEHW)
#if defined(__3DO__)
#define FRAME_WIDTH 320
#define FRAME_HEIGHT 240
#elif defined(__NDS__)
#define FRAME_WIDTH 256
#define FRAME_HEIGHT 192
#endif
#elif defined(MODE4)
#define VRAM_WIDTH 120 // in shorts (240 bytes)
#define FRAME_WIDTH 240
#define FRAME_HEIGHT 160
#elif defined(MODE13)
#define VRAM_WIDTH 160 // in shorts (320 bytes)
#define FRAME_WIDTH 320
#if defined(__TNS__)
#define FRAME_HEIGHT 240 // MODE X?
#else
#define FRAME_HEIGHT 200
#endif
#endif
#define VRAM_WIDTH (FRAME_WIDTH/2) // in shorts
// Optimization flags =========================================================
#ifdef __GBA__
@ -143,6 +149,23 @@
#define FAST_HITMASK
#endif
#ifdef __32X__
// hide dead enemies after a while to reduce the number of polygons on the screen
#define HIDE_CORPSES (30*10) // 10 sec
// replace trap flor geometry by two flat quads in the static state
#define LOD_TRAP_FLOOR
// disable some plants environment to reduce overdraw of transparent geometry
#define NO_STATIC_MESH_PLANTS
// use IWRAM_CODE section that faster for matrix interpolation (GBA only)
#define IWRAM_MATRIX_LERP
// the maximum of active enemies
#define MAX_ENEMIES 3
// visibility distance
#define VIEW_DIST (1024 * 10)
// skip collideSpheres for enemies
#define FAST_HITMASK
#endif
#ifndef NAV_STEPS
#define NAV_STEPS 5
#endif
@ -190,16 +213,24 @@ typedef unsigned int uint32;
typedef uint16 divTableInt;
#endif
#if defined(__3DO__)
//#include <new>
inline void* operator new(size_t, void *ptr)
{
return ptr;
}
#if defined(__3DO__) || defined(__32X__)
X_INLINE int32 abs(int32 x) {
return (x >= 0) ? x : -x;
}
#endif
#if defined(__GBA__) || defined(__NDS__)
#if defined(__GBA__) || defined(__NDS__) || defined(__32X__)
#define int2str(x,str) itoa(x, str, 10)
#elif defined(__3DO__)
#define int2str(x,str) sprintf(str, "%d", x)
#elif defined(__TNS__)
#define int2str(x,str) __itoa(x, str, 10)
#else
#define int2str(x,str) _itoa(x, str, 10)
#endif
@ -436,7 +467,7 @@ extern int32 fps;
#define MAX_TEXTURES 1536
#define MAX_SPRITES 180
#define MAX_FACES 1920
#define MAX_ROOM_LIST 16
#define MAX_ROOM_LIST 32
#define MAX_PORTALS 16
#define MAX_CAUSTICS 32
#define MAX_RAND_TABLE 32
@ -521,10 +552,11 @@ enum InputKey {
IK_C = (1 << 6),
IK_X = (1 << 7),
IK_Y = (1 << 8),
IK_L = (1 << 9),
IK_R = (1 << 10),
IK_START = (1 << 11),
IK_SELECT = (1 << 12)
IK_Z = (1 << 9),
IK_L = (1 << 10),
IK_R = (1 << 11),
IK_START = (1 << 12),
IK_SELECT = (1 << 13)
};
// action keys (ItemObj::input)
@ -1322,6 +1354,9 @@ struct Camera {
bool lastFixed;
bool center;
void initCinematic();
void updateCinematic();
void init(ItemObj* lara);
Location getLocationForAngle(int32 angle, int32 distH, int32 distV);
void clip(Location &loc);
@ -1517,6 +1552,8 @@ struct ExtraInfoLara
extern ExtraInfoLara playersExtra[MAX_PLAYERS];
#define gCinematicCamera playersExtra[0].camera
struct Enemy;
enum EnemyMood
@ -1993,6 +2030,14 @@ struct Box
uint16 overlap;
};
struct CameraFrame
{
vec3s target;
vec3s pos;
int16 fov;
int16 roll;
};
struct Level
{
uint32 magic;
@ -2037,7 +2082,7 @@ struct Level
const uint16* zones[2][ZONE_MAX];
const int16* animTexData;
const ItemObjInfo* itemsInfo;
uint32 cameraFrames;
const CameraFrame* cameraFrames;
const uint16* soundMap;
const SoundInfo* soundsInfo;
const uint8* soundData;
@ -2645,6 +2690,13 @@ vec3i boxPushOut(const AABBi &a, const AABBi &b);
void flush_c();
#endif
#ifdef __32X__ // TODO
#undef matrixPush
#define matrixPush matrixPush_asm
extern "C" void matrixPush_asm();
#endif
#define matrixPop() gMatrixPtr--
X_INLINE vec3i matrixGetDir(const Matrix &m)
@ -2678,6 +2730,7 @@ void drawText(int32 x, int32 y, const char* text, TextAlign align);
void drawModel(const ItemObj* item);
void drawItem(const ItemObj* item);
void drawRooms(Camera* camera);
void drawCinematicRooms();
void drawHUD(Lara* lara);
void drawNodesLerp(const ItemObj* item, const AnimFrame* frameA, const AnimFrame* frameB, int32 frameDelta, int32 frameRate);

View File

@ -771,6 +771,48 @@ void drawRooms(Camera* camera)
setViewport(vp);
}
void drawCinematicRooms()
{
RectMinMax vp = viewport;
#if 1
gCinematicCamera.view.room->clip = viewport;
Room** visRoom = gCinematicCamera.view.room->getVisibleRooms();
// draw rooms and objects
while (*visRoom)
{
Room* room = *visRoom++;
drawRoom(room);
room->reset();
}
#else
for (int32 i = 0; i < level.roomsCount; i++)
{
rooms[i].clip = vp;
}
for (int32 i = 0; i < level.roomsCount; i++)
{
if (rooms[i].info->alternateRoom != NO_ROOM) {
rooms[rooms[i].info->alternateRoom].clip.x0 = 0xFFFF;
}
}
for (int32 i = 0; i < level.roomsCount; i++)
{
const Room* room = rooms + i;
if (room->clip.x0 == 0xFFFF)
continue;
drawRoom(room);
}
#endif
setPaletteIndex(0);
setViewport(vp);
}
void drawHUD(Lara* lara)
{
int32 x = (FRAME_WIDTH - (100 + 2 + 2)) - 4;

View File

@ -149,6 +149,11 @@ void gameLoadLevel(const void* data)
}
ItemObj::sFirstFree = items + level.itemsCount;
for (int32 i = 0; i < MAX_PLAYERS; i++)
{
players[i] = NULL;
}
if (gLevelID == LVL_TR1_TITLE) {
// init dummy Lara for updateInput()
items->extraL = playersExtra;
@ -173,13 +178,19 @@ void gameLoadLevel(const void* data)
item->angle.y = ((info->flags >> 14) - 2) * ANGLE_90;
item->flags = info->flags;
if (item->type == ITEM_LARA || item->type == ITEM_CUT_1) {
if (item->type == ITEM_LARA) {
players[0] = (Lara*)item;
}
item->init(rooms + info->roomIndex);
}
if (isCutsceneLevel())
{
gCinematicCamera.initCinematic();
}
// gym
//resetLara(0, 7, _vec3i(39038, -1280, 51712), ANGLE_90); // start
//resetLara(0, 8, _vec3i(55994, 0, 52603), ANGLE_90); // piano
@ -233,10 +244,17 @@ void updateItems()
item = next;
}
for (int32 i = 0; i < MAX_PLAYERS; i++)
if (isCutsceneLevel())
{
if (players[i]) {
players[i]->update();
gCinematicCamera.updateCinematic();
}
else
{
for (int32 i = 0; i < MAX_PLAYERS; i++)
{
if (players[i]) {
players[i]->update();
}
}
}
}
@ -306,9 +324,17 @@ void gameRender()
{
// TODO set viewports for coop
#ifndef PROFILE_SOUNDTIME
drawRooms(&players[i]->extraL->camera);
if (isCutsceneLevel()) {
drawCinematicRooms();
} else {
drawRooms(&players[i]->extraL->camera);
}
#endif
drawHUD(players[i]);
if (players[i])
{
drawHUD(players[i]);
}
}
} else {
inventory.draw();

View File

@ -937,7 +937,7 @@ int32 ItemObj::getSpheres(Sphere* spheres, bool flag) const
#include "enemy.h"
#include "object.h"
#ifdef __GBA__
#ifdef __GNUC__
// ItemObj ctor is called on existing and pre-filled memory
#pragma GCC diagnostic ignored "-Wuninitialized"
#endif
@ -992,7 +992,7 @@ ItemObj::ItemObj(Room* room)
room->add(this);
}
#ifdef __GBA__
#ifdef __GNUC__
#pragma GCC diagnostic warning "-Wuninitialized"
#endif
@ -1472,10 +1472,10 @@ ItemObj* ItemObj::init(Room* room)
// INIT_ITEM( GEARS_1 , ??? );
// INIT_ITEM( GEARS_2 , ??? );
// INIT_ITEM( GEARS_3 , ??? );
// INIT_ITEM( CUT_1 , ??? );
// INIT_ITEM( CUT_2 , ??? );
// INIT_ITEM( CUT_3 , ??? );
// INIT_ITEM( CUT_4 , ??? );
INIT_ITEM( CUT_1 , CinematicObject );
INIT_ITEM( CUT_2 , CinematicObject );
INIT_ITEM( CUT_3 , CinematicObject );
INIT_ITEM( CUT_4 , CinematicObject );
// INIT_ITEM( INV_PASSPORT_CLOSED , ??? );
// INIT_ITEM( INV_MAP , ??? );
INIT_ITEM( CRYSTAL , Crystal );

View File

@ -2737,6 +2737,14 @@ struct Lara : ItemObj
if (keys & IK_L) input |= IN_LOOK;
if (keys & IK_R) input |= IN_WALK;
}
#elif defined(__32X__)
// 6 buttons
if (keys & IK_A) input |= IN_JUMP;
if (keys & IK_B) input |= IN_ACTION;
if (keys & IK_C) input |= IN_WEAPON;
if (keys & IK_X) input |= IN_WALK;
if (keys & IK_Y) input |= IN_UP | IN_DOWN;
if (keys & IK_Z) input |= IN_LOOK;
#elif defined(__GBA__) || defined(_WIN32)
int32 ikA, ikB;

View File

@ -224,4 +224,12 @@ int32 getAmbientTrack()
return gLevelInfo[gLevelID].track;
}
bool isCutsceneLevel()
{
return (gLevelID == LVL_TR1_CUT_1) ||
(gLevelID == LVL_TR1_CUT_2) ||
(gLevelID == LVL_TR1_CUT_3) ||
(gLevelID == LVL_TR1_CUT_4);
}
#endif

View File

@ -335,6 +335,35 @@ struct TrapDoor : Object
};
struct CinematicObject : Object
{
CinematicObject(Room* room) : Object(room)
{
angle.y = 0;
if (type == ITEM_CUT_1)
{
gCinematicCamera.view.pos = pos;
gCinematicCamera.view.room = room;
}
flags |= ITEM_FLAG_SHADOW;
activate();
}
virtual void update()
{
if (type == ITEM_CUT_1 || type == ITEM_CUT_2 || type == ITEM_CUT_3)
{
pos = playersExtra[0].camera.view.pos;
angle.y = playersExtra[0].camera.targetAngle.y;
}
animProcess();
}
};
struct Crystal : Object
{
Crystal(Room* room) : Object(room)

128
src/platform/32x/32x.h Normal file
View File

@ -0,0 +1,128 @@
#ifndef __32X_H__
#define __32X_H__
#define MARS_CRAM (*(volatile unsigned short *)0x20004200)
#define MARS_FRAMEBUFFER (*(volatile unsigned short *)0x24000000)
#define MARS_OVERWRITE_IMG (*(volatile unsigned short *)0x24020000)
#define MARS_SDRAM (*(volatile unsigned short *)0x26000000)
#define MARS_SYS_INTMSK (*(volatile unsigned short *)0x20004000)
#define MARS_SYS_DMACTR (*(volatile unsigned short *)0x20004006)
#define MARS_SYS_DMASAR (*(volatile unsigned long *)0x20004008)
#define MARS_SYS_DMADAR (*(volatile unsigned long *)0x2000400C)
#define MARS_SYS_DMALEN (*(volatile unsigned short *)0x20004010)
#define MARS_SYS_DMAFIFO (*(volatile unsigned short *)0x20004012)
#define MARS_SYS_VRESI_CLR (*(volatile unsigned short *)0x20004014)
#define MARS_SYS_VINT_CLR (*(volatile unsigned short *)0x20004016)
#define MARS_SYS_HINT_CLR (*(volatile unsigned short *)0x20004018)
#define MARS_SYS_CMDI_CLR (*(volatile unsigned short *)0x2000401A)
#define MARS_SYS_PWMI_CLR (*(volatile unsigned short *)0x2000401C)
#define MARS_SYS_COMM0 (*(volatile unsigned short *)0x20004020) /* Master SH2 communication */
#define MARS_SYS_COMM2 (*(volatile unsigned short *)0x20004022)
#define MARS_SYS_COMM4 (*(volatile unsigned short *)0x20004024) /* Slave SH2 communication */
#define MARS_SYS_COMM6 (*(volatile unsigned short *)0x20004026)
#define MARS_SYS_COMM8 (*(volatile unsigned short *)0x20004028) /* controller 1 current value */
#define MARS_SYS_COMM10 (*(volatile unsigned short *)0x2000402A) /* controller 2 current value */
#define MARS_SYS_COMM12 (*(volatile unsigned long *)0x2000402C) /* vcount current value */
#define MARS_PWM_CTRL (*(volatile unsigned short *)0x20004030)
#define MARS_PWM_CYCLE (*(volatile unsigned short *)0x20004032)
#define MARS_PWM_LEFT (*(volatile unsigned short *)0x20004034)
#define MARS_PWM_RIGHT (*(volatile unsigned short *)0x20004036)
#define MARS_PWM_MONO (*(volatile unsigned short *)0x20004038)
#define MARS_VDP_DISPMODE (*(volatile unsigned short *)0x20004100)
#define MARS_VDP_FILLEN (*(volatile unsigned short *)0x20004104)
#define MARS_VDP_FILADR (*(volatile unsigned short *)0x20004106)
#define MARS_VDP_FILDAT (*(volatile unsigned short *)0x20004108)
#define MARS_VDP_FBCTL (*(volatile unsigned short *)0x2000410A)
#define MARS_SH2_ACCESS_VDP 0x8000
#define MARS_68K_ACCESS_VDP 0x0000
#define MARS_PAL_FORMAT 0x0000
#define MARS_NTSC_FORMAT 0x8000
#define MARS_VDP_PRIO_68K 0x0000
#define MARS_VDP_PRIO_32X 0x0080
#define MARS_224_LINES 0x0000
#define MARS_240_LINES 0x0040
#define MARS_VDP_MODE_OFF 0x0000
#define MARS_VDP_MODE_256 0x0001
#define MARS_VDP_MODE_32K 0x0002
#define MARS_VDP_MODE_RLE 0x0003
#define MARS_VDP_VBLK 0x8000
#define MARS_VDP_HBLK 0x4000
#define MARS_VDP_PEN 0x2000
#define MARS_VDP_FEN 0x0002
#define MARS_VDP_FS 0x0001
#define SH2_CCTL_CP 0x10
#define SH2_CCTL_TW 0x08
#define SH2_CCTL_CE 0x01
#define SH2_FRT_TIER (*(volatile unsigned char *)0xFFFFFE10)
#define SH2_FRT_FTCSR (*(volatile unsigned char *)0xFFFFFE11)
#define SH2_FRT_FRCH (*(volatile unsigned char *)0xFFFFFE12)
#define SH2_FRT_FRCL (*(volatile unsigned char *)0xFFFFFE13)
#define SH2_FRT_OCRH (*(volatile unsigned char *)0xFFFFFE14)
#define SH2_FRT_OCRL (*(volatile unsigned char *)0xFFFFFE15)
#define SH2_FRT_TCR (*(volatile unsigned char *)0xFFFFFE16)
#define SH2_FRT_TOCR (*(volatile unsigned char *)0xFFFFFE17)
#define SH2_FRT_ICRH (*(volatile unsigned char *)0xFFFFFE18)
#define SH2_FRT_ICRL (*(volatile unsigned char *)0xFFFFFE19)
#define SH2_DMA_SAR0 (*(volatile unsigned long *)0xFFFFFF80)
#define SH2_DMA_DAR0 (*(volatile unsigned long *)0xFFFFFF84)
#define SH2_DMA_TCR0 (*(volatile unsigned long *)0xFFFFFF88)
#define SH2_DMA_CHCR0 (*(volatile unsigned long *)0xFFFFFF8C)
#define SH2_DMA_VCR0 (*(volatile unsigned long *)0xFFFFFFA0)
#define SH2_DMA_DRCR0 (*(volatile unsigned char *)0xFFFFFE71)
#define SH2_DMA_SAR1 (*(volatile unsigned long *)0xFFFFFF90)
#define SH2_DMA_DAR1 (*(volatile unsigned long *)0xFFFFFF94)
#define SH2_DMA_TCR1 (*(volatile unsigned long *)0xFFFFFF98)
#define SH2_DMA_CHCR1 (*(volatile unsigned long *)0xFFFFFF9C)
#define SH2_DMA_VCR1 (*(volatile unsigned long *)0xFFFFFFA8)
#define SH2_DMA_DRCR1 (*(volatile unsigned char *)0xFFFFFE72)
#define SH2_DMA_DMAOR (*(volatile unsigned long *)0xFFFFFFB0)
#define SH2_INT_IPRA (*(volatile unsigned short *)0xFFFFFEE2)
#define SEGA_CTRL_UP 0x0001
#define SEGA_CTRL_DOWN 0x0002
#define SEGA_CTRL_LEFT 0x0004
#define SEGA_CTRL_RIGHT 0x0008
#define SEGA_CTRL_B 0x0010
#define SEGA_CTRL_C 0x0020
#define SEGA_CTRL_A 0x0040
#define SEGA_CTRL_START 0x0080
#define SEGA_CTRL_Z 0x0100
#define SEGA_CTRL_Y 0x0200
#define SEGA_CTRL_X 0x0400
#define SEGA_CTRL_MODE 0x0800
#define SEGA_CTRL_TYPE 0xF000
#define SEGA_CTRL_THREE 0x0000
#define SEGA_CTRL_SIX 0x1000
#define SEGA_CTRL_NONE 0xF000
#define MASTER_STATUS_OK 1
#define SLAVE_STATUS_OK 2
#define MASTER_LOCK 4
#define SLAVE_LOCK 8
/* global functions in sh2_crt0.s */
extern "C"
{
void fast_memcpy(void *dst, const void *src, int len);
void fast_memset(void *dst, int value, int len);
void CacheControl(int mode);
void CacheClearLine(void* ptr);
}
#endif

91
src/platform/32x/Makefile Normal file
View File

@ -0,0 +1,91 @@
ifdef $(GENDEV)
ROOTDIR = $(GENDEV)
else
ROOTDIR = /opt/toolchains/sega
endif
TARGET = OpenLara
BUILD = build
SOURCES = . asm ../../fixed
LDSCRIPTSDIR = $(ROOTDIR)/ldscripts
SHPREFIX = $(ROOTDIR)/sh-elf/bin/sh-elf-
SHCC = $(SHPREFIX)gcc
SHXX = $(SHPREFIX)g++
SHAS = $(SHPREFIX)as
SHLD = $(SHPREFIX)ld
SHOBJC = $(SHPREFIX)objcopy
CC_VER := $(shell $(SHCC) -dumpversion)
MDPREFIX = $(ROOTDIR)/m68k-elf/bin/m68k-elf-
MDAS = $(MDPREFIX)as
MDLD = $(MDPREFIX)ld
LIBPATH = -L$(ROOTDIR)/sh-elf/lib -L$(ROOTDIR)/sh-elf/lib/gcc/sh-elf/$(CC_VER) -L$(ROOTDIR)/sh-elf/sh-elf/lib
INCPATH = -I. -I../../fixed -I$(ROOTDIR)/sh-elf/include -I$(ROOTDIR)/sh-elf/sh-elf/include
SHCCFLAGS = -D__32X__ -m2 -mb -O2 -Wall -g -c -fno-rtti -fno-exceptions -fno-asynchronous-unwind-tables -fomit-frame-pointer -ffast-math -Wno-class-memaccess
SHLDFLAGS = -T $(LDSCRIPTSDIR)/mars.ld -Wl,-Map=$(BUILD)/output.map -nostdlib
SHASFLAGS = --big
MDLDFLAGS = -T $(LDSCRIPTSDIR)/md.ld --oformat binary
MDASFLAGS = -m68000 --register-prefix-optional
DD = dd
RM = rm -f
FILES_AS = $(foreach dir, $(SOURCES), $(wildcard $(dir)/*.s))
FILES_CC = $(foreach dir, $(SOURCES), $(wildcard $(dir)/*.c))
FILES_XX = $(foreach dir, $(SOURCES), $(wildcard $(dir)/*.cpp))
LIBS = $(LIBPATH) -lm -lc -lgcc -lgcc-Os-4-200 -lnosys
OBJS = $(BUILD)/sh2_crt0.o
OBJS += $(addprefix $(BUILD)/, $(notdir $(FILES_AS:%.s=%.o)))
OBJS += $(addprefix $(BUILD)/, $(notdir $(FILES_CC:%.c=%.o)))
OBJS += $(addprefix $(BUILD)/, $(notdir $(FILES_XX:%.cpp=%.o)))
.PHONY: dump clean
all: $(BUILD) m68k_crt0.bin m68k_crt1.bin $(TARGET).32x
dump:
@[ -d dump ] || mkdir -p dump
$(SHXX) $(SHCCFLAGS) $(INCPATH) -S -o dump/main.s main.cpp
$(SHXX) $(SHCCFLAGS) $(INCPATH) -S -o dump/render.s render.cpp
$(SHXX) $(SHCCFLAGS) $(INCPATH) -S -o dump/sound.s sound.cpp
$(SHXX) $(SHCCFLAGS) $(INCPATH) -S -o dump/common.s ../../fixed/common.cpp
$(BUILD):
@[ -d $@ ] || mkdir -p $@
$(TARGET).32x: $(TARGET).elf
$(SHOBJC) -O binary $< temp.bin
$(DD) if=temp.bin of=$@ bs=1024K conv=sync
$(RM) -f temp.bin
$(TARGET).elf: $(OBJS)
$(SHCC) $(SHLDFLAGS) $(OBJS) $(LIBS) -o $(TARGET).elf
%.bin: crt/%.s
$(MDAS) $(MDASFLAGS) -o $(BUILD)/$@.o $<
$(MDLD) $(MDLDFLAGS) -o $(BUILD)/$@ $(BUILD)/$@.o
$(BUILD)/%.o: crt/%.s
$(SHAS) $(SHASFLAGS) $(INCPATH) -o $@ $<
$(BUILD)/%.o: asm/%.s
$(SHAS) $(SHASFLAGS) $(INCPATH) -o $@ $<
$(BUILD)/%.o: %.c
$(SHCC) $(SHCCFLAGS) $(INCPATH) -o $@ $<
$(BUILD)/%.o: %.cpp
$(SHXX) $(SHCCFLAGS) $(INCPATH) -o $@ $<
$(BUILD)/%.o: ../../fixed/%.cpp
$(SHXX) $(SHCCFLAGS) $(INCPATH) -o $@ $<
clean:
$(RM) $(BUILD)/* *.32x *.elf

View File

@ -0,0 +1,17 @@
.text
/*
.global _TITLE_PKD
.align 4
_TITLE_PKD:
.long TITLE
TITLE:
.incbin "data/TITLE.PKD"
*/
.global _LEVEL1_PKD
.align 4
_LEVEL1_PKD:
.long LEVEL1
LEVEL1:
.incbin "data/LEVEL1.PKD"
.align 4

View File

@ -0,0 +1,42 @@
.text
.global _matrixPush_asm
_matrixPush_asm:
mov.l .var_matrixPtr, r5
mov.l @r5, r0
/* row[0] */
mov.l @r0+, r1
mov.l @r0+, r2
mov.l @r0+, r3
mov.l @r0+, r4
mov.l r1, @(32, r0)
mov.l r2, @(36, r0)
mov.l r3, @(40, r0)
mov.l r4, @(44, r0)
/* row[1] */
mov.l @r0+, r1
mov.l @r0+, r2
mov.l @r0+, r3
mov.l @r0+, r4
mov.l r1, @(32, r0)
mov.l r2, @(36, r0)
mov.l r3, @(40, r0)
mov.l r4, @(44, r0)
/* row[2] */
mov.l @r0+, r1
mov.l @r0+, r2
mov.l @r0+, r3
mov.l @r0+, r4
mov.l r1, @(32, r0)
mov.l r2, @(36, r0)
mov.l r3, @(40, r0)
mov.l r4, @(44, r0)
rts
mov.l r0, @r5
.var_matrixPtr:
.long _gMatrixPtr

View File

@ -0,0 +1,85 @@
| SEGA 32X support code for the 68000
| by Chilly Willy
| First part of rom header
.text
| Initial exception vectors. When the console is first turned on, it is
| in MegaDrive mode. All vectors just point to the code to start up the
| Mars adapter. After the adapter is enabled, none of these vectors will
| appear as the adpater uses its own vector table to route exceptions to
| the jump table. 0x3F0 is where the 68000 starts at for the 32X.
.long 0x01000000,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0
.long 0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0
.long 0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0
.long 0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0
.long 0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0
.long 0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0
.long 0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0
.long 0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0,0x000003F0
| Standard MegaDrive ROM header at 0x100
.ascii "SEGA 32X " /* First 4 bytes must be "SEGA" */
.ascii "XProger (c)2022 " /* Copyright and date */
.ascii "OpenLara Alpha " /* JP Name */
.ascii "OpenLara Alpha " /* EN Name */
.ascii "GM 14021968-01" /* Serial No. */
.word 0x0000
.ascii "J6 "
.long 0x00000000,0x003FFFFF /* ROM start, end */
.long 0x00FF0000,0x00FFFFFF /* RAM start, end */
| .ascii "RA" /* External RAM */
| .byte 0xF8 /* don't clear + odd bytes */
| .byte 0x20 /* SRAM */
| .long 0x00200001,0x0020FFFF /* SRAM start, end */
.ascii " " /* no SRAM */
.ascii " "
.ascii " "
.ascii " "
.ascii " "
.ascii "F " /* enable any hardware configuration */
| Mars exception vector jump table at 0x200
jmp 0x880800.l /* reset = hot start */
jsr 0x880806.l /* EX_BusError */
jsr 0x880806.l /* EX_AddrError */
jsr 0x880806.l /* EX_IllInstr */
jsr 0x880806.l /* EX_DivByZero */
jsr 0x880806.l /* EX_CHK */
jsr 0x880806.l /* EX_TrapV */
jsr 0x880806.l /* EX_Priviledge */
jsr 0x880806.l /* EX_Trace */
jsr 0x880806.l /* EX_LineA */
jsr 0x880806.l /* EX_LineF */
.space 72 /* reserved */
jsr 0x880806.l /* EX_Spurious */
jsr 0x880806.l /* EX_Level1 */
jsr 0x880806.l /* EX_Level2 */
jsr 0x880806.l /* EX_Level3 */
jmp 0x88080C.l /* EX_Level4 HBlank */
jsr 0x880806.l /* EX_Level5 */
jmp 0x880812.l /* EX_Level6 VBlank */
jsr 0x880806.l /* EX_Level7 */
jsr 0x880806.l /* EX_Trap0 */
jsr 0x880806.l /* EX_Trap1 */
jsr 0x880806.l /* EX_Trap2 */
jsr 0x880806.l /* EX_Trap3 */
jsr 0x880806.l /* EX_Trap4 */
jsr 0x880806.l /* EX_Trap5 */
jsr 0x880806.l /* EX_Trap6 */
jsr 0x880806.l /* EX_Trap7 */
jsr 0x880806.l /* EX_Trap8 */
jsr 0x880806.l /* EX_Trap9 */
jsr 0x880806.l /* EX_TrapA */
jsr 0x880806.l /* EX_TrapB */
jsr 0x880806.l /* EX_TrapC */
jsr 0x880806.l /* EX_TrapD */
jsr 0x880806.l /* EX_TrapE */
jsr 0x880806.l /* EX_TrapF */
.space 166 /* reserved */

View File

@ -0,0 +1,548 @@
| SEGA 32X support code for the 68000
| by Chilly Willy
| Third part of rom header
.text
| Standard Mars startup code at 0x3F0 - this is included as binary as SEGA
| uses this as a security key. US law allows us to include this as-is because
| it's used for security. The interoperability clauses in the law state this
| trumps copyright... and the Supreme Court agrees. :P
.word 0x287C,0xFFFF,0xFFC0,0x23FC,0x0000,0x0000,0x00A1,0x5128
.word 0x46FC,0x2700,0x4BF9,0x00A1,0x0000,0x7001,0x0CAD,0x4D41
.word 0x5253,0x30EC,0x6600,0x03E6,0x082D,0x0007,0x5101,0x67F8
.word 0x4AAD,0x0008,0x6710,0x4A6D,0x000C,0x670A,0x082D,0x0000
.word 0x5101,0x6600,0x03B8,0x102D,0x0001,0x0200,0x000F,0x6706
.word 0x2B78,0x055A,0x4000,0x7200,0x2C41,0x4E66,0x41F9,0x0000
.word 0x04D4,0x6100,0x0152,0x6100,0x0176,0x47F9,0x0000,0x04E8
.word 0x43F9,0x00A0,0x0000,0x45F9,0x00C0,0x0011,0x3E3C,0x0100
.word 0x7000,0x3B47,0x1100,0x3B47,0x1200,0x012D,0x1100,0x66FA
.word 0x7425,0x12DB,0x51CA,0xFFFC,0x3B40,0x1200,0x3B40,0x1100
.word 0x3B47,0x1200,0x149B,0x149B,0x149B,0x149B,0x41F9,0x0000
.word 0x04C0,0x43F9,0x00FF,0x0000,0x22D8,0x22D8,0x22D8,0x22D8
.word 0x22D8,0x22D8,0x22D8,0x22D8,0x41F9,0x00FF,0x0000,0x4ED0
.word 0x1B7C,0x0001,0x5101,0x41F9,0x0000,0x06BC,0xD1FC,0x0088
.word 0x0000,0x4ED0,0x0404,0x303C,0x076C,0x0000,0x0000,0xFF00
.word 0x8137,0x0002,0x0100,0x0000,0xAF01,0xD91F,0x1127,0x0021
.word 0x2600,0xF977,0xEDB0,0xDDE1,0xFDE1,0xED47,0xED4F,0xD1E1
.word 0xF108,0xD9C1,0xD1E1,0xF1F9,0xF3ED,0x5636,0xE9E9,0x9FBF
.word 0xDFFF,0x4D41,0x5253,0x2049,0x6E69,0x7469,0x616C,0x2026
.word 0x2053,0x6563,0x7572,0x6974,0x7920,0x5072,0x6F67,0x7261
.word 0x6D20,0x2020,0x2020,0x2020,0x2020,0x2043,0x6172,0x7472
.word 0x6964,0x6765,0x2056,0x6572,0x7369,0x6F6E,0x2020,0x2020
.word 0x436F,0x7079,0x7269,0x6768,0x7420,0x5345,0x4741,0x2045
.word 0x4E54,0x4552,0x5052,0x4953,0x4553,0x2C4C,0x5444,0x2E20
.word 0x3139,0x3934,0x2020,0x2020,0x2020,0x2020,0x2020,0x2020
.word 0x2020,0x2020,0x2020,0x2020,0x2020,0x2020,0x2020,0x2020
.word 0x2020,0x2020,0x2020,0x524F,0x4D20,0x5665,0x7273,0x696F
.word 0x6E20,0x312E,0x3000,0x48E7,0xC040,0x43F9,0x00C0,0x0004
.word 0x3011,0x303C,0x8000,0x323C,0x0100,0x3E3C,0x0012,0x1018
.word 0x3280,0xD041,0x51CF,0xFFF8,0x4CDF,0x0203,0x4E75,0x48E7
.word 0x81C0,0x41F9,0x0000,0x063E,0x43F9,0x00C0,0x0004,0x3298
.word 0x3298,0x3298,0x3298,0x3298,0x3298,0x3298,0x2298,0x3341
.word 0xFFFC,0x3011,0x0800,0x0001,0x66F8,0x3298,0x3298,0x7000
.word 0x22BC,0xC000,0x0000,0x7E0F,0x3340,0xFFFC,0x3340,0xFFFC
.word 0x3340,0xFFFC,0x3340,0xFFFC,0x51CF,0xFFEE,0x22BC,0x4000
.word 0x0010,0x7E09,0x3340,0xFFFC,0x3340,0xFFFC,0x3340,0xFFFC
.word 0x3340,0xFFFC,0x51CF,0xFFEE,0x4CDF,0x0381,0x4E75,0x8114
.word 0x8F01,0x93FF,0x94FF,0x9500,0x9600,0x9780,0x4000,0x0080
.word 0x8104,0x8F02,0x48E7,0xC140,0x43F9,0x00A1,0x5180,0x08A9
.word 0x0007,0xFF80,0x66F8,0x3E3C,0x00FF,0x7000,0x7200,0x337C
.word 0x00FF,0x0004,0x3341,0x0006,0x3340,0x0008,0x4E71,0x0829
.word 0x0001,0x000B,0x66F8,0x0641,0x0100,0x51CF,0xFFE8,0x4CDF
.word 0x0283,0x4E75,0x48E7,0x8180,0x41F9,0x00A1,0x5200,0x08A8
.word 0x0007,0xFF00,0x66F8,0x3E3C,0x001F,0x20C0,0x20C0,0x20C0
.word 0x20C0,0x51CF,0xFFF6,0x4CDF,0x0181,0x4E75,0x41F9,0x00FF
.word 0x0000,0x3E3C,0x07FF,0x7000,0x20C0,0x20C0,0x20C0,0x20C0
.word 0x20C0,0x20C0,0x20C0,0x20C0,0x51CF,0xFFEE,0x3B7C,0x0000
.word 0x1200,0x7E0A,0x51CF,0xFFFE,0x43F9,0x00A1,0x5100,0x7000
.word 0x2340,0x0020,0x2340,0x0024,0x1B7C,0x0003,0x5101,0x2E79
.word 0x0088,0x0000,0x0891,0x0007,0x66FA,0x7000,0x3340,0x0002
.word 0x3340,0x0004,0x3340,0x0006,0x2340,0x0008,0x2340,0x000C
.word 0x3340,0x0010,0x3340,0x0030,0x3340,0x0032,0x3340,0x0038
.word 0x3340,0x0080,0x3340,0x0082,0x08A9,0x0000,0x008B,0x66F8
.word 0x6100,0xFF12,0x08E9,0x0000,0x008B,0x67F8,0x6100,0xFF06
.word 0x08A9,0x0000,0x008B,0x6100,0xFF3C,0x303C,0x0040,0x2229
.word 0x0020,0x0C81,0x5351,0x4552,0x6700,0x0092,0x303C,0x0080
.word 0x2229,0x0020,0x0C81,0x5344,0x4552,0x6700,0x0080,0x21FC
.word 0x0088,0x02A2,0x0070,0x303C,0x0002,0x7200,0x122D,0x0001
.word 0x1429,0x0080,0xE14A,0x8242,0x0801,0x000F,0x660A,0x0801
.word 0x0006,0x6700,0x0058,0x6008,0x0801,0x0006,0x6600,0x004E
.word 0x7020,0x41F9,0x0088,0x0000,0x3C28,0x018E,0x4A46,0x6700
.word 0x0010,0x3429,0x0028,0x0C42,0x0000,0x67F6,0xB446,0x662C
.word 0x7000,0x2340,0x0028,0x2340,0x002C,0x3E14,0x2C7C,0xFFFF
.word 0xFFC0,0x4CD6,0x7FF9,0x44FC,0x0000,0x6014,0x43F9,0x00A1
.word 0x5100,0x3340,0x0006,0x303C,0x8000,0x6004,0x44FC,0x0001
| At this point (0x800), the Work RAM is clear, the VDP initialized, the
| VRAM/VSRAM/CRAM cleared, the Z80 initialized, the 32X initialized,
| both 32X framebuffers cleared, the 32X palette cleared, the SH2s
| checked for a startup error, the adapter TV mode matches the MD TV
| mode, and the ROM checksum checked. If any error is detected, the
| carry is set, otherwise it is cleared. The 68000 main code is now
| entered.
jmp __start+0x00880000+0x3F0
| 68000 General exception handler at 0x806
jmp __except+0x00880000+0x3F0
| 68000 Level 4 interrupt handler at 0x80C - HBlank IRQ
jmp __hblank+0x00880000+0x3F0
| 68000 Level 6 interrupt handler at 0x812 - VBlank IRQ
jmp __vblank+0x00880000+0x3F0
__except:
move.l d0,-(sp)
move.l 4(sp),d0 /* jump table return address */
sub.w #0x206,d0 /* 0 = BusError, 6 = AddrError, etc */
| handle exception
move.l (sp)+,d0
addq.l #4,sp /* pop jump table return address */
rte
__hblank:
rte
__vblank:
move.l d0,-(sp)
move.l 0xFF0FFC,d0
beq.b 1f
move.l a0,-(sp)
movea.l d0,a0
jmp (a0)
1:
move.l (sp)+,d0
rte
__start:
move.b #0,0xA15107 /* clear RV - allow SH2 to access ROM */
0:
cmp.l #0x4D5F4F4B,0xA15120 /* M_OK */
bne.b 0b /* wait for master ok */
1:
cmp.l #0x535F4F4B,0xA15124 /* S_OK */
bne.b 1b /* wait for slave ok */
| init joyports
move.b #0x40,0xA10009
move.b #0x40,0xA1000B
move.b #0x40,0xA10003
move.b #0x40,0xA10005
| init MD VDP
lea 0xC00004,a0
move.w #0x8004,(a0) /* reg. 0 - Disable HBL INT */
move.w #0x8174,(a0) /* reg. 1 - Enable display, VBL INT, DMA + 28 VCell size */
move.w #0x8230,(a0) /* reg. 2 - Plane A =$30*$400=$C000 */
move.w #0x832C,(a0) /* reg. 3 - Window =$2C*$400=$B000 */
move.w #0x8407,(a0) /* reg. 4 - Plane B =$7*$2000=$E000 */
move.w #0x855E,(a0) /* reg. 5 - sprite table begins at $BC00=$5E*$200 */
move.w #0x8600,(a0) /* reg. 6 - not used */
move.w #0x8700,(a0) /* reg. 7 - Background Color number*/
move.w #0x8800,(a0) /* reg. 8 - not used */
move.w #0x8900,(a0) /* reg. 9 - not used */
move.w #0x8A01,(a0) /* reg 10 - HInterrupt timing */
move.w #0x8B00,(a0) /* reg 11 - $0000abcd a=extr.int b=vscr cd=hscr */
move.w #0x8C81,(a0) /* reg 12 - hcell mode + shadow/highight + interlaced mode (40 cell, no shadow, no interlace)*/
move.w #0x8D2E,(a0) /* reg 13 - HScroll Table = $B800 */
move.w #0x8E00,(a0) /* reg 14 - not used */
move.w #0x8F02,(a0) /* reg 15 - auto increment data */
move.w #0x9011,(a0) /* reg 16 - scrl screen v&h size (64x64) */
move.w #0x9100,(a0) /* reg 17 - window hpos */
move.w #0x92FF,(a0) /* reg 18 - window vpos */
| Copy 68000 main loop to Work RAM to keep contention for the ROM with
| SH2s to a minimum.
lea __m68k_start(pc),a0
lea 0x00FF1000,a1
move.w #__m68k_end-__m68k_start-1,d0
cpyloop:
move.b (a0)+,(a1)+
dbra d0,cpyloop
move.w #0,0xA15128 /* controller 1 */
move.w #0,0xA1512A /* controller 2 */
| look for mouse
lea 0xA10003,a0
0:
bsr get_mky
cmpi.l #-2,d0
beq.b 0b /* timeout */
cmpi.l #-1,d0
beq.b 1f /* no mouse */
move.w #0xF001,0xA15128 /* mouse in port 1 */
1:
lea 2(a0),a0
2:
bsr get_mky
cmpi.l #-2,d0
beq.b 2b /* timeout */
cmpi.l #-1,d0
beq.b 3f /* no mouse */
move.w #0xF001,0xA1512A /* mouse in port 2 */
3:
move.l #0,0xA1512C /* clear the vblank count */
| jump to main loop in Work RAM
jmp 0xFF1000.l
| this block of code must be pc relative as it's copied into Work RAM
__m68k_start:
move.b #1,0xA15107 /* set RV */
move.b #2,0xA130F1 /* SRAM disabled, write protected */
move.b #0,0xA15107 /* clear RV */
move.w 0xA15100,d0
or.w #0x8000,d0
move.w d0,0xA15100 /* set FM - allow SH2 access to MARS hw */
move.l #0,0xA15120 /* let Master SH2 run */
lea vert_blank(pc),a0
move.l a0,0xFF0FFC /* set vertical blank interrupt handler */
move.w #0x2000,sr /* enable interrupts */
main_loop:
move.w 0xA15120,d0 /* get COMM0 */
bne.b handle_req
| any other 68000 tasks here
bra.b main_loop
| process request from Master SH2
handle_req:
cmpi.w #0x01FF,d0
bls read_sram
cmpi.w #0x02FF,d0
bls write_sram
cmpi.w #0x03FF,d0
bls start_music
cmpi.w #0x04FF,d0
bls stop_music
cmpi.w #0x05FF,d0
bls read_mouse
| unknown command
move.w #0,0xA15120 /* done */
bra.b main_loop
read_sram:
move.w #0x2700,sr /* disable ints */
moveq #0,d1
moveq #0,d0
move.w 0xA15122,d0 /* COMM2 holds offset */
lea 0x200000,a0
move.b #1,0xA15107 /* set RV */
move.b #3,0xA130F1 /* SRAM enabled, write protected */
move.b 1(a0,d0.l),d1 /* read SRAM */
move.b #2,0xA130F1 /* SRAM disabled, write protected */
move.b #0,0xA15107 /* clear RV */
move.w d1,0xA15122 /* COMM2 holds return byte */
move.w #0,0xA15120 /* done */
move.w #0x2000,sr /* enable ints */
bra main_loop
write_sram:
move.w #0x2700,sr /* disable ints */
moveq #0,d1
move.w 0xA15122,d1 /* COMM2 holds offset */
lea 0x200000,a0
move.b #1,0xA15107 /* set RV */
move.b #1,0xA130F1 /* SRAM enabled, write enabled */
move.b d0,1(a0,d1.l) /* write SRAM */
move.b #2,0xA130F1 /* SRAM disabled, write protected */
move.b #0,0xA15107 /* clear RV */
move.w #0,0xA15120 /* done */
move.w #0x2000,sr /* enable ints */
bra main_loop
set_rom_bank:
move.l a0,d3
swap d3
lsr.w #4,d3
andi.w #3,d3
move.w d3,0xA15104 /* set ROM bank select */
move.l a0,d3
andi.l #0x0FFFFF,d3
ori.l #0x900000,d3
movea.l d3,a1
rts
start_music:
stop_music:
move.w #0,0xA15120 /* done */
bra main_loop
read_mouse:
tst.b d0
bne.b 1f /* skip port 1 */
move.w 0xA15128,d0
andi.w #0xF001,d0
cmpi.w #0xF001,d0
bne.b 1f /* no mouse in port 1 */
lea 0xA10003,a0
bsr get_mky
bset #31,d0
move.w d0,0xA15122
swap d0
move.w d0,0xA15120
0:
move.w 0xA15120,d0
bne.b 0b /* wait for SH2 to read mouse value */
bra main_loop
1:
move.w 0xA1512A,d0
andi.w #0xF001,d0
cmpi.w #0xF001,d0
bne.b 3f /* no mouse in port 2 */
lea 0xA10005,a0
bsr get_mky
bset #31,d0
move.w d0,0xA15122
swap d0
move.w d0,0xA15120
2:
move.w 0xA15120,d0
bne.b 2b /* wait for SH2 to read mouse value */
bra main_loop
3:
move.l #-1,d0 /* no mouse */
move.w d0,0xA15122
swap d0
move.w d0,0xA15120
4:
move.w 0xA15120,d0
bne.b 4b /* wait for SH2 to read mouse value */
bra main_loop
vert_blank:
move.l d1,-(sp)
move.l d2,-(sp)
/* read controllers */
move.w 0xA15128,d0
andi.w #0xF000,d0
cmpi.w #0xF000,d0
beq.b 0f /* no pad in port 1 (or mouse) */
lea 0xA10003,a0
bsr.b get_pad
move.w d2,0xA15128 /* controller 1 current value */
0:
move.w 0xA1512A,d0
andi.w #0xF000,d0
cmpi.w #0xF000,d0
beq.b 1f /* no pad in port 2 (or mouse) */
lea 0xA10005,a0
bsr.b get_pad
move.w d2,0xA1512A /* controller 2 current value */
1:
move.l 0xA1512C,d0
addq.l #1,d0
move.l d0,0xA1512C /* increment the vblank count */
move.l (sp)+,d2
move.l (sp)+,d1
movea.l (sp)+,a0
move.l (sp)+,d0
rte
| get current pad value
| entry: a0 = pad control port
| exit: d2 = pad value (0 0 0 1 M X Y Z S A C B R L D U) or (0 0 0 0 0 0 0 0 S A C B R L D U)
get_pad:
bsr.b get_input /* - 0 s a 0 0 d u - 1 c b r l d u */
move.w d0,d1
andi.w #0x0C00,d0
bne.b no_pad
bsr.b get_input /* - 0 s a 0 0 d u - 1 c b r l d u */
bsr.b get_input /* - 0 s a 0 0 0 0 - 1 c b m x y z */
move.w d0,d2
bsr.b get_input /* - 0 s a 1 1 1 1 - 1 c b r l d u */
andi.w #0x0F00,d0 /* 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 */
cmpi.w #0x0F00,d0
beq.b common /* six button pad */
move.w #0x010F,d2 /* three button pad */
common:
lsl.b #4,d2 /* - 0 s a 0 0 0 0 m x y z 0 0 0 0 */
lsl.w #4,d2 /* 0 0 0 0 m x y z 0 0 0 0 0 0 0 0 */
andi.w #0x303F,d1 /* 0 0 s a 0 0 0 0 0 0 c b r l d u */
move.b d1,d2 /* 0 0 0 0 m x y z 0 0 c b r l d u */
lsr.w #6,d1 /* 0 0 0 0 0 0 0 0 s a 0 0 0 0 0 0 */
or.w d1,d2 /* 0 0 0 0 m x y z s a c b r l d u */
eori.w #0x1FFF,d2 /* 0 0 0 1 M X Y Z S A C B R L D U */
rts
no_pad:
move.w #0xF000,d2
rts
| read single phase from controller
get_input:
move.b #0x00,(a0)
nop
nop
move.b (a0),d0
move.b #0x40,(a0)
lsl.w #8,d0
move.b (a0),d0
rts
| get current mouse value
| entry: a0 = mouse control port
| exit: d0 = mouse value (0 0 0 0 0 0 0 0 YO XO YS XS S M R L X7 X6 X5 X4 X3 X2 X1 X0 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0) or -2 (timeout) or -1 (no mouse)
get_mky:
move.w sr,d2
move.w #0x2700,sr /* disable ints */
move.b #0x60,6(a0) /* set direction bits */
nop
nop
move.b #0x60,(a0) /* first phase of mouse packet */
nop
nop
0:
btst #4,(a0)
beq.b 0b /* wait on handshake */
move.b (a0),d0
andi.b #15,d0
bne mky_err /* not 0 means not mouse */
move.b #0x20,(a0) /* next phase */
move.w #254,d1 /* number retries before timeout */
1:
btst #4,(a0)
bne.b 2f /* handshake */
dbra d1,1b
bra timeout_err
2:
move.b (a0),d0
andi.b #15,d0
move.b #0,(a0) /* next phase */
cmpi.b #11,d0
bne mky_err /* not 11 means not mouse */
3:
btst #4,(a0)
beq.b 4f /* handshake */
dbra d1,3b
bra timeout_err
4:
move.b (a0),d0 /* specs say should be 15 */
nop
nop
move.b #0x20,(a0) /* next phase */
nop
nop
5:
btst #4,(a0)
bne.b 6f
dbra d1,5b
bra timeout_err
6:
move.b (a0),d0 /* specs say should be 15 */
nop
nop
move.b #0,(a0) /* next phase */
moveq #0,d0 /* clear reg to hold packet */
nop
7:
btst #4,(a0)
beq.b 8f /* handshake */
dbra d1,7b
bra timeout_err
8:
move.b (a0),d0 /* YO XO YS XS */
move.b #0x20,(a0) /* next phase */
lsl.w #8,d0 /* save nibble */
9:
btst #4,(a0)
bne.b 10f /* handshake */
dbra d1,9b
bra timeout_err
10:
move.b (a0),d0 /* S M R L */
move.b #0,(a0) /* next phase */
lsl.b #4,d0 /* YO XO YS XS S M R L 0 0 0 0 */
lsl.l #4,d0 /* YO XO YS XS S M R L 0 0 0 0 0 0 0 0 */
11:
btst #4,(a0)
beq.b 12f /* handshake */
dbra d1,11b
bra timeout_err
12:
move.b (a0),d0 /* X7 X6 X5 X4 */
move.b #0x20,(a0) /* next phase */
lsl.b #4,d0 /* YO XO YS XS S M R L X7 X6 X5 X4 0 0 0 0 */
lsl.l #4,d0 /* YO XO YS XS S M R L X7 X6 X5 X4 0 0 0 0 0 0 0 0 */
13:
btst #4,(a0)
bne.b 14f /* handshake */
dbra d1,13b
bra timeout_err
14:
move.b (a0),d0 /* X3 X2 X1 X0 */
move.b #0,(a0) /* next phase */
lsl.b #4,d0 /* YO XO YS XS S M R L X7 X6 X5 X4 X3 X2 X1 X0 0 0 0 0 */
lsl.l #4,d0 /* YO XO YS XS S M R L X7 X6 X5 X4 X3 X2 X1 X0 0 0 0 0 0 0 0 0 */
15:
btst #4,(a0)
beq.b 16f /* handshake */
dbra d1,15b
bra timeout_err
16:
move.b (a0),d0 /* Y7 Y6 Y5 Y4 */
move.b #0x20,(a0) /* next phase */
lsl.b #4,d0 /* YO XO YS XS S M R L X7 X6 X5 X4 X3 X2 X1 X0 Y7 Y6 Y5 Y4 0 0 0 0 */
lsl.l #4,d0 /* YO XO YS XS S M R L X7 X6 X5 X4 X3 X2 X1 X0 Y7 Y6 Y5 Y4 0 0 0 0 0 0 0 0*/
17:
btst #4,(a0)
beq.b 18f /* handshake */
dbra d1,17b
bra timeout_err
18:
move.b (a0),d0 /* Y3 Y2 Y1 Y0 */
move.b #0x60,(a0) /* first phase */
lsl.b #4,d0 /* YO XO YS XS S M R L X7 X6 X5 X4 X3 X2 X1 X0 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 0 0 0 0 */
lsr.l #4,d0 /* YO XO YS XS S M R L X7 X6 X5 X4 X3 X2 X1 X0 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
19:
btst #4,(a0)
beq.b 19b /* wait on handshake */
move.w d2,sr /* restore int status */
rts
timeout_err:
move.b #0x60,(a0) /* first phase */
nop
nop
0:
btst #4,(a0)
beq.b 0b /* wait on handshake */
move.w d2,sr /* restore int status */
moveq #-2,d0
rts
mky_err:
move.b #0x40,6(a0) /* set direction bits */
nop
nop
move.b #0x40,(a0)
move.w d2,sr /* restore int status */
moveq #-1,d0
rts
__m68k_end:
.align 4

View File

@ -0,0 +1,719 @@
! SEGA 32X support code for SH2
! by Chilly Willy
! Rom header and SH2 init/exception code - must be first in object list
.text
! Standard MD Header at 0x000
.incbin "build/m68k_crt0.bin", 0, 0x3C0
! Standard Mars Header at 0x3C0
.ascii "OpenLara " /* module name */
.long 0x00000000 /* version */
.long __text_size /* Source (in ROM) */
.long 0x00000000 /* Destination (in SDRAM) */
.long __data_size /* Size */
.long 0x06000240 /* Master SH2 Jump */
.long 0x06000244 /* Slave SH2 Jump */
.long 0x06000000 /* Master SH2 VBR */
.long 0x06000120 /* Slave SH2 VBR */
! Standard MD startup code at 0x3F0
.incbin "build/m68k_crt1.bin"
.data
! Master Vector Base Table at 0x06000000
.long mstart /* Cold Start PC */
.long 0x0603FC00 /* Cold Start SP */
.long mstart /* Manual Reset PC */
.long 0x0603FC00 /* Manual Reset SP */
.long main_err /* Illegal instruction */
.long 0x00000000 /* reserved */
.long main_err /* Invalid slot instruction */
.long 0x20100400 /* reserved */
.long 0x20100420 /* reserved */
.long main_err /* CPU address error */
.long main_err /* DMA address error */
.long main_err /* NMI vector */
.long main_err /* User break vector */
.space 76 /* reserved */
.long main_err /* TRAPA #32 */
.long main_err /* TRAPA #33 */
.long main_err /* TRAPA #34 */
.long main_err /* TRAPA #35 */
.long main_err /* TRAPA #36 */
.long main_err /* TRAPA #37 */
.long main_err /* TRAPA #38 */
.long main_err /* TRAPA #39 */
.long main_err /* TRAPA #40 */
.long main_err /* TRAPA #41 */
.long main_err /* TRAPA #42 */
.long main_err /* TRAPA #43 */
.long main_err /* TRAPA #44 */
.long main_err /* TRAPA #45 */
.long main_err /* TRAPA #46 */
.long main_err /* TRAPA #47 */
.long main_err /* TRAPA #48 */
.long main_err /* TRAPA #49 */
.long main_err /* TRAPA #50 */
.long main_err /* TRAPA #51 */
.long main_err /* TRAPA #52 */
.long main_err /* TRAPA #53 */
.long main_err /* TRAPA #54 */
.long main_err /* TRAPA #55 */
.long main_err /* TRAPA #56 */
.long main_err /* TRAPA #57 */
.long main_err /* TRAPA #58 */
.long main_err /* TRAPA #59 */
.long main_err /* TRAPA #60 */
.long main_err /* TRAPA #61 */
.long main_err /* TRAPA #62 */
.long main_err /* TRAPA #63 */
.long main_irq /* Level 1 IRQ */
.long main_irq /* Level 2 & 3 IRQ's */
.long main_irq /* Level 4 & 5 IRQ's */
.long main_irq /* PWM interupt */
.long main_irq /* Command interupt */
.long main_irq /* H Blank interupt */
.long main_irq /* V Blank interupt */
.long main_irq /* Reset Button */
! Slave Vector Base Table at 0x06000120
.long sstart /* Cold Start PC */
.long 0x06040000 /* Cold Start SP */
.long sstart /* Manual Reset PC */
.long 0x06040000 /* Manual Reset SP */
.long slav_err /* Illegal instruction */
.long 0x00000000 /* reserved */
.long slav_err /* Invalid slot instruction */
.long 0x20100400 /* reserved */
.long 0x20100420 /* reserved */
.long slav_err /* CPU address error */
.long slav_err /* DMA address error */
.long slav_err /* NMI vector */
.long slav_err /* User break vector */
.space 76 /* reserved */
.long slav_err /* TRAPA #32 */
.long slav_err /* TRAPA #33 */
.long slav_err /* TRAPA #34 */
.long slav_err /* TRAPA #35 */
.long slav_err /* TRAPA #36 */
.long slav_err /* TRAPA #37 */
.long slav_err /* TRAPA #38 */
.long slav_err /* TRAPA #39 */
.long slav_err /* TRAPA #40 */
.long slav_err /* TRAPA #41 */
.long slav_err /* TRAPA #42 */
.long slav_err /* TRAPA #43 */
.long slav_err /* TRAPA #44 */
.long slav_err /* TRAPA #45 */
.long slav_err /* TRAPA #46 */
.long slav_err /* TRAPA #47 */
.long slav_err /* TRAPA #48 */
.long slav_err /* TRAPA #49 */
.long slav_err /* TRAPA #50 */
.long slav_err /* TRAPA #51 */
.long slav_err /* TRAPA #52 */
.long slav_err /* TRAPA #53 */
.long slav_err /* TRAPA #54 */
.long slav_err /* TRAPA #55 */
.long slav_err /* TRAPA #56 */
.long slav_err /* TRAPA #57 */
.long slav_err /* TRAPA #58 */
.long slav_err /* TRAPA #59 */
.long slav_err /* TRAPA #60 */
.long slav_err /* TRAPA #61 */
.long slav_err /* TRAPA #62 */
.long slav_err /* TRAPA #63 */
.long slav_irq /* Level 1 IRQ */
.long slav_irq /* Level 2 & 3 IRQ's */
.long slav_irq /* Level 4 & 5 IRQ's */
.long slav_irq /* PWM interupt */
.long slav_irq /* Command interupt */
.long slav_irq /* H Blank interupt */
.long slav_irq /* V Blank interupt */
.long slav_irq /* Reset Button */
! The main SH2 starts here at 0x06000240
mstart:
bra mcont
nop
! The slave SH2 starts here at 0x06000244
sstart:
bra scont
nop
! Each section of code below has its own data table so that the code
! can be extended without worrying about the offsets becoming too big.
! This results in duplicate entries, but not so many that we care. :)
mcont:
! clear interrupt flags
mov.l _master_int_clr,r1
mov.w r0,@-r1 /* PWM INT clear */
mov.w r0,@r1
mov.w r0,@-r1 /* CMD INT clear */
mov.w r0,@r1
mov.w r0,@-r1 /* H INT clear */
mov.w r0,@r1
mov.w r0,@-r1 /* V INT clear */
mov.w r0,@r1
mov.w r0,@-r1 /* VRES INT clear */
mov.w r0,@r1
mov.l _master_stk,r15
! purge cache and turn it off
mov.l _master_cctl,r0
mov #0x10,r1
mov.b r1,@r0
! clear bss
mov #0,r0
mov.l _master_bss_start,r1
mov.l _master_bss_end,r2
0:
mov.l r0,@r1
cmp/eq r1,r2
bf/s 0b
add #4,r1
! wait for 68000 to finish init
mov.l _master_sts,r0
mov.l _master_ok,r1
1:
mov.l @r0,r2
nop
nop
cmp/eq r1,r2
bt 1b
! let Slave SH2 run
mov #0,r1
mov.l r1,@(4,r0) /* clear slave status */
mov #0x80,r0
mov.l _master_adapter,r1
mov.b r0,@r1 /* set FM */
mov #0x00,r0
mov.b r0,@(1,r1) /* set int enables */
mov #0x20,r0
ldc r0,sr /* allow ints */
! purge cache, turn it on, and run main()
mov.l _master_cctl,r0
mov #0x11,r1
mov.b r1,@r0
mov.l _master_go,r0
jmp @r0
nop
.align 2
_master_int_clr:
.long 0x2000401E /* one word passed last int clr reg */
_master_stk:
.long 0x0603FC00 /* Cold Start SP */
_master_sts:
.long 0x20004020
_master_ok:
.ascii "M_OK"
_master_adapter:
.long 0x20004000
_master_cctl:
.long 0xFFFFFE92
_master_go:
.long _main
_master_bss_start:
.long __bss_start
_master_bss_end:
.long __bss_end
scont:
! clear interrupt flags
mov.l _slave_int_clr,r1
mov.w r0,@-r1 /* PWM INT clear */
mov.w r0,@r1
mov.w r0,@-r1 /* CMD INT clear */
mov.w r0,@r1
mov.w r0,@-r1 /* H INT clear */
mov.w r0,@r1
mov.w r0,@-r1 /* V INT clear */
mov.w r0,@r1
mov.w r0,@-r1 /* VRES INT clear */
mov.w r0,@r1
mov.l _slave_stk,r15
! wait for Master SH2 and 68000 to finish init
mov.l _slave_sts,r0
mov.l _slave_ok,r1
1:
mov.l @r0,r2
nop
nop
cmp/eq r1,r2
bt 1b
mov.l _slave_adapter,r1
mov #0x00,r0
mov.b r0,@(1,r1) /* set int enables (different from master despite same address!) */
mov #0x20,r0
ldc r0,sr /* allow ints */
! purge cache, turn it on, and run slave()
mov.l _slave_cctl,r0
mov #0x11,r1
mov.b r1,@r0
mov.l _slave_go,r0
jmp @r0
nop
.align 2
_slave_int_clr:
.long 0x2000401E /* one word passed last int clr reg */
_slave_stk:
.long 0x06040000 /* Cold Start SP */
_slave_sts:
.long 0x20004024
_slave_ok:
.ascii "S_OK"
_slave_adapter:
.long 0x20004000
_slave_cctl:
.long 0xFFFFFE92
_slave_go:
.long _slave
! Master exception handler
main_err:
rte
nop
! Master IRQ handler
main_irq:
mov.l r0,@-r15
stc sr,r0 /* SR holds IRQ level in I3-I0 */
shlr2 r0
and #0x38,r0
cmp/eq #0x28,r0
bt main_h_irq
cmp/eq #0x18,r0
bt main_pwm_irq
cmp/eq #0x30,r0
bt main_v_irq
cmp/eq #0x20,r0
bt main_cmd_irq
cmp/eq #0x38,r0
bt main_vres_irq
mov.l @r15+,r0
rte
nop
main_v_irq:
mov.l r1,@-r15
mov.l mvi_mars_adapter,r1
mov.w r0,@(0x16,r1) /* clear V IRQ */
nop
nop
nop
nop
! handle V IRQ
mov.l @r15+,r1
mov.l @r15+,r0
rte
nop
.align 2
mvi_mars_adapter:
.long 0x20004000
main_h_irq:
mov.l r1,@-r15
mov.l mhi_mars_adapter,r1
mov.w r0,@(0x18,r1) /* clear H IRQ */
nop
nop
nop
nop
! handle H IRQ
mov.l @r15+,r1
mov.l @r15+,r0
rte
nop
.align 2
mhi_mars_adapter:
.long 0x20004000
main_cmd_irq:
mov.l r1,@-r15
mov.l mci_mars_adapter,r1
mov.w r0,@(0x1A,r1) /* clear CMD IRQ */
nop
nop
nop
nop
! handle CMD IRQ
mov.l @r15+,r1
mov.l @r15+,r0
rte
nop
.align 2
mci_mars_adapter:
.long 0x20004000
main_pwm_irq:
mov.l r1,@-r15
mov.l mpi_mars_adapter,r1
mov.w r0,@(0x1C,r1) /* clear PWM IRQ */
nop
nop
nop
nop
! handle PWM IRQ
mov.l @r15+,r1
mov.l @r15+,r0
rte
nop
.align 2
mpi_mars_adapter:
.long 0x20004000
main_vres_irq:
mov.l mvri_mars_adapter,r1
mov.w r0,@(0x14,r1) /* clear VRES IRQ */
nop
nop
nop
nop
mov #0x0F,r0
shll2 r0
shll2 r0
ldc r0,sr /* disallow ints */
mov.l mvri_master_stk,r15
mov.l mvri_master_vres,r0
jmp @r0
nop
.align 2
mvri_mars_adapter:
.long 0x20004000
mvri_master_stk:
.long 0x0603FC00 /* Cold Start SP */
mvri_master_vres:
.long main_reset
! Slave exception handler
slav_err:
rte
nop
! Slave IRQ handler
slav_irq:
mov.l r0,@-r15
stc sr,r0 /* SR holds IRQ level I3-I0 */
shlr2 r0
and #0x38,r0
cmp/eq #0x28,r0
bt slav_h_irq
cmp/eq #0x18,r0
bt slav_pwm_irq
cmp/eq #0x30,r0
bt slav_v_irq
cmp/eq #0x20,r0
bt slav_cmd_irq
cmp/eq #0x38,r0
bt slav_vres_irq
mov.l @r15+,r0
rte
nop
slav_v_irq:
mov.l r1,@-r15
mov.l svi_mars_adapter,r1
mov.w r0,@(0x16,r1) /* clear V IRQ */
nop
nop
nop
nop
! handle V IRQ
mov.l @r15+,r1
mov.l @r15+,r0
rte
nop
.align 2
svi_mars_adapter:
.long 0x20004000
slav_h_irq:
mov.l r1,@-r15
mov.l shi_mars_adapter,r1
mov.w r0,@(0x18,r1) /* clear H IRQ */
nop
nop
nop
nop
! handle H IRQ
mov.l @r15+,r1
mov.l @r15+,r0
rte
nop
.align 2
shi_mars_adapter:
.long 0x20004000
slav_cmd_irq:
mov.l r1,@-r15
mov.l sci_mars_adapter,r1
mov.w r0,@(0x1A,r1) /* clear CMD IRQ */
nop
nop
nop
nop
! handle CMD IRQ
mov.l @r15+,r1
mov.l @r15+,r0
rte
nop
.align 2
sci_mars_adapter:
.long 0x20004000
slav_pwm_irq:
mov.l r1,@-r15
mov.l spi_mars_adapter,r1
mov.w r0,@(0x1C,r1) /* clear PWM IRQ */
nop
nop
nop
nop
! handle PWM IRQ
mov.l @r15+,r1
mov.l @r15+,r0
rte
nop
.align 2
spi_mars_adapter:
.long 0x20004000
slav_vres_irq:
mov.l svri_mars_adapter,r1
mov.w r0,@(0x14,r1) /* clear VRES IRQ */
nop
nop
nop
nop
mov #0x0F,r0
shll2 r0
shll2 r0
ldc r0,sr /* disallow ints */
mov.l svri_slave_stk,r15
mov.l svri_slave_vres,r0
jmp @r0
nop
.align 2
svri_mars_adapter:
.long 0x20004000
svri_slave_stk:
.long 0x06040000 /* Cold Start SP */
svri_slave_vres:
.long slav_reset
! Fast memcpy function - copies longs, runs from sdram for speed
! On entry: r4 = dst, r5 = src, r6 = len (in longs)
.align 4
.global _fast_memcpy
_fast_memcpy:
mov.l @r5+,r3
mov.l r3,@r4
dt r6
bf/s _fast_memcpy
add #4,r4
rts
nop
! Fast memset function - sets long values, runs from sdram for speed
! On entry: r4 = dst, r5 = value, r6 = len (in longs)
.align 4
.global _fast_memset
_fast_memset:
mov.l r5,@r4
dt r6
bf/s _fast_memset
add #4,r4
rts
nop
! Cache clear line function
! On entry: r4 = ptr - should be 16 byte aligned
.align 4
.global _CacheClearLine
_CacheClearLine:
mov.l _cache_flush,r0
or r0,r4
mov #0,r0
mov.l r0,@r4
rts
nop
.align 2
_cache_flush:
.long 0x40000000
! Cache control function
! On entry: r4 = cache mode => 0x10 = CP, 0x08 = TW, 0x01 = CE
.align 4
.global _CacheControl
_CacheControl:
mov.l _sh2_cctl,r0
mov.b r4,@r0
rts
nop
.align 2
_sh2_cctl:
.long 0xFFFFFE92
main_reset:
! do any master SH2 specific reset code here
mov.l slav_st,r0
mov.l slav_ok,r1
0:
mov.l @r0,r2
nop
nop
cmp/eq r1,r2
bf 0b /* wait for slave */
! recopy rom data to sdram
mov.l rom_header,r1
mov.l @r1,r2 /* src relative to start of rom */
mov.l @(4,r1),r3 /* dst relative to start of sdram */
mov.l @(8,r1),r4 /* size (longword aligned) */
mov.l rom_start,r1
add r1,r2
mov.l sdram_start,r1
add r1,r3
shlr2 r4 /* number of longs */
add #-1,r4
1:
mov.l @r2+,r0
mov.l r0,@r3
add #4,r3
dt r4
bf 1b
mov.l main_st,r0
mov.l main_ok,r1
mov.l r1,@r0 /* tell everyone reset complete */
mov.l main_go,r0
jmp @r0
nop
slav_reset:
! do any slave SH2 specific reset code here
mov.l slav_st,r0
mov.l slav_ok,r1
mov.l r1,@r0 /* tell master to start reset */
mov.l main_st,r0
mov.l main_ok,r1
0:
mov.l @r0,r2
nop
nop
cmp/eq r1,r2
bf 0b /* wait for master to do the work */
mov.l slav_go,r0
jmp @r0
nop
.align 2
main_st:
.long 0x20004020
main_ok:
.ascii "M_OK"
main_go:
.long mstart
rom_header:
.long 0x220003D4
rom_start:
.long 0x22000000
sdram_start:
.long 0x26000000
slav_st:
.long 0x20004024
slav_ok:
.ascii "S_OK"
slav_go:
.long sstart
.global _start
_start:

View File

@ -0,0 +1,3 @@
make clean
make
/c/RetroArch/retroarch.exe -L C:\\RetroArch\\cores\\picodrive_libretro.dll OpenLara.32x

149
src/platform/32x/main.cpp Normal file
View File

@ -0,0 +1,149 @@
const void* TRACKS_IMA;
const void* TITLE_SCR;
extern void* LEVEL1_PKD;
#include "game.h"
int32 fps;
void osSetPalette(const uint16* palette)
{
void *dst = (void*)&MARS_CRAM;
memcpy(dst, palette, 256 * 2);
}
int32 osGetSystemTimeMS()
{
return 0;
}
bool osSaveSettings()
{
return false;
}
bool osLoadSettings()
{
return false;
}
bool osCheckSave()
{
return false;
}
bool osSaveGame()
{
return false;
}
bool osLoadGame()
{
return false;
}
void osJoyVibrate(int32 index, int32 L, int32 R)
{
// nope
}
void updateInput()
{
keys = 0;
uint16 mask = MARS_SYS_COMM8;
if (mask & SEGA_CTRL_UP) keys |= IK_UP;
if (mask & SEGA_CTRL_RIGHT) keys |= IK_RIGHT;
if (mask & SEGA_CTRL_DOWN) keys |= IK_DOWN;
if (mask & SEGA_CTRL_LEFT) keys |= IK_LEFT;
if (mask & SEGA_CTRL_A) keys |= IK_A;
if (mask & SEGA_CTRL_B) keys |= IK_B;
if (mask & SEGA_CTRL_C) keys |= IK_C;
if (mask & SEGA_CTRL_X) keys |= IK_X;
if (mask & SEGA_CTRL_Y) keys |= IK_Y;
if (mask & SEGA_CTRL_Z) keys |= IK_Z;
if (mask & SEGA_CTRL_START) keys |= IK_START;
if (mask & SEGA_CTRL_MODE) keys |= IK_SELECT;
}
void* osLoadLevel(const char* name)
{
return (void*)LEVEL1_PKD;
}
uint16 pageIndex = 0;
void pageWait()
{
while ((MARS_VDP_FBCTL & MARS_VDP_FS) != pageIndex);
}
void pageFlip()
{
pageIndex ^= 1;
MARS_VDP_FBCTL = pageIndex;
}
extern "C" void slave(void)
{
// TODO
}
int main()
{
while ((MARS_SYS_INTMSK & MARS_SH2_ACCESS_VDP) == 0);
MARS_VDP_DISPMODE = MARS_224_LINES | MARS_VDP_MODE_256;
for (int32 page = 0; page < 2; page++)
{
pageFlip();
pageWait();
volatile uint16* lineTable = &MARS_FRAMEBUFFER;
uint16 wordOffset = 0x100;
for (int32 i = 0; i < 224; i++, wordOffset += FRAME_WIDTH / 2)
{
lineTable[i] = wordOffset;
}
uint8* fb = (uint8*)(lineTable + 0x100);
memset(fb, 0, 0x10000 - 0x200);
}
gameInit(gLevelInfo[gLevelID].name);
int32 lastFrame = (MARS_SYS_COMM12 >> 1) - 1;
while (1)
{
int32 frame = MARS_SYS_COMM12;
if (!(MARS_VDP_DISPMODE & MARS_NTSC_FORMAT))
{
frame = frame * 6 / 5; // PAL fix
}
frame >>= 1;
int32 delta = frame - lastFrame;
if (!delta)
continue;
lastFrame = frame;
updateInput();
gameUpdate(delta);
pageWait();
gameRender();
pageFlip();
}
return 0;
}

View File

@ -0,0 +1,809 @@
#ifndef H_RASTERIZER_MODE13
#define H_RASTERIZER_MODE13
#include "common.h"
extern uint8 gLightmap[256 * 32];
extern const uint8* gTile;
#define rasterizeS rasterizeS_c
#define rasterizeF rasterizeF_c
#define rasterizeG rasterizeG_c
#define rasterizeFT rasterizeFT_c
#define rasterizeGT rasterizeGT_c
#define rasterizeFTA rasterizeFTA_c
#define rasterizeGTA rasterizeGTA_c
#define rasterizeSprite rasterizeSprite_c
#define rasterizeLineH rasterizeLineH_c
#define rasterizeLineV rasterizeLineV_c
#define rasterizeFillS rasterizeFillS_c
void rasterizeS_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
const uint8* ft_lightmap = &gLightmap[0x1A00];
int32 Lh = 0;
int32 Rh = 0;
int32 Ldx = 0;
int32 Rdx = 0;
int32 Rx;
int32 Lx;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
if (Lh > 1)
{
uint32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
}
Lx <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
if (Rh > 1) {
uint32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
}
Rx <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
volatile uint8* ptr = (uint8*)pixel + x1;
if (x1 & 1)
{
ptr[0] = ft_lightmap[ptr[0]];
ptr++;
width--;
}
if (width & 1)
{
width--;
ptr[width] = ft_lightmap[ptr[width]];
}
while (width)
{
uint16 p = *(uint16*)ptr;
uint16 index = ft_lightmap[p & 0xFF];
index |= ft_lightmap[p >> 8] << 8;
*(uint16*)ptr = index;
ptr += 2;
width -= 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
}
}
}
void rasterizeF_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
uint32 color = (uint32)R;
color = gLightmap[(L->v.g << 8) | color];
color |= (color << 8);
int32 Lh = 0;
int32 Rh = 0;
int32 Ldx = 0;
int32 Rdx = 0;
int32 Rx;
int32 Lx;
R = L;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
ASSERT(L->v.y >= 0);
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
if (Lh > 1)
{
uint32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
}
Lx <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
ASSERT(R->v.y >= 0);
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
if (Rh > 1) {
uint32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
}
Rx <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
*ptr++ = uint8(color);
width--;
}
if (width & 1)
{
ptr[width - 1] = uint8(color);
}
if (width & 2)
{
*(uint16*)ptr = color;
ptr += 2;
}
width >>= 2;
while (width--)
{
*(uint16*)ptr = color;
ptr += 2;
*(uint16*)ptr = color;
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
}
}
}
void rasterizeG_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
int32 Lh = 0, Rh = 0;
int32 Lx, Rx, Ldx = 0, Rdx = 0;
int32 Lg, Rg, Ldg = 0, Rdg = 0;
const uint8* ft_lightmap = gLightmap + L->t.t;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
Lg = L->v.g;
if (Lh > 1)
{
int32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
Ldg = tmp * (N->v.g - Lg);
}
Lx <<= 16;
Lg <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
Rg = R->v.g;
if (Rh > 1)
{
int32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
Rdg = tmp * (N->v.g - Rg);
}
Rx <<= 16;
Rg <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
int32 tmp = FixedInvU(width);
int32 dgdx = tmp * ((Rg - Lg) >> 5) >> 10;
int32 g = Lg;
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
*ptr++ = ft_lightmap[g >> 16 << 8];
g += dgdx >> 1;
width--;
}
if (width & 1)
{
ptr[width - 1] = ft_lightmap[Rg >> 16 << 8];
}
if (width & 2)
{
uint8 p = ft_lightmap[g >> 16 << 8];
g += dgdx;
*(uint16*)ptr = p | (p << 8);
ptr += 2;
}
width >>= 2;
while (width--)
{
uint8 p;
p = ft_lightmap[g >> 16 << 8];
*(uint16*)ptr = p | (p << 8);
g += dgdx;
ptr += 2;
p = ft_lightmap[g >> 16 << 8];
*(uint16*)ptr = p | (p << 8);
g += dgdx;
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
Lg += Ldg;
Rg += Rdg;
}
}
}
void rasterizeFT_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
const uint8* ft_lightmap = &gLightmap[L->v.g << 8];
int32 Lh = 0, Rh = 0;
int32 Lx, Rx, Ldx = 0, Rdx = 0;
uint32 Lt, Rt, Ldt, Rdt;
Ldt = 0;
Rdt = 0;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
Lt = L->t.t;
if (Lh > 1)
{
int32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
uint32 duv = N->t.t - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Ldt = (du & 0xFFFF0000) | (dv >> 16);
}
Lx <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
Rt = R->t.t;
if (Rh > 1)
{
int32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
uint32 duv = N->t.t - Rt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Rdt = (du & 0xFFFF0000) | (dv >> 16);
}
Rx <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
uint32 tmp = FixedInvU(width);
uint32 duv = Rt - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
uint32 dtdx = (du & 0xFFFF0000) | (dv >> 16);
uint32 t = Lt;
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
*ptr++ = ft_lightmap[gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
width--;
}
if (width & 1)
{
uint32 tmp = Rt - dtdx;
ptr[width - 1] = ft_lightmap[gTile[(tmp & 0xFF00) | (tmp >> 24)]];
}
width >>= 1;
while (width--)
{
uint8 indexA = ft_lightmap[gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
uint8 indexB = ft_lightmap[gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
#ifdef CPU_BIG_ENDIAN
*(uint16*)ptr = indexB | (indexA << 8);
#else
*(uint16*)ptr = indexA | (indexB << 8);
#endif
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
Lt += Ldt;
Rt += Rdt;
}
}
}
void rasterizeGT_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
#ifdef ALIGNED_LIGHTMAP
ASSERT((intptr_t(gLightmap) & 0xFFFF) == 0); // lightmap should be 64k aligned
#endif
int32 Lh = 0, Rh = 0;
int32 Lx, Rx, Lg, Rg, Ldx = 0, Rdx = 0, Ldg = 0, Rdg = 0;
uint32 Lt, Rt, Ldt, Rdt;
Ldt = 0;
Rdt = 0;
// 8-bit fractional part precision for Gouraud component
// has some artifacts but allow to save one reg for inner loop
// for aligned by 64k address of lightmap array
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
Lg = L->v.g;
Lt = L->t.t;
if (Lh > 1)
{
int32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
Ldg = tmp * (N->v.g - Lg) >> 8;
uint32 duv = N->t.t - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Ldt = (du & 0xFFFF0000) | (dv >> 16);
}
Lx <<= 16;
Lg <<= 8;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
Rg = R->v.g;
Rt = R->t.t;
if (Rh > 1)
{
int32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
Rdg = tmp * (N->v.g - Rg) >> 8;
uint32 duv = N->t.t - Rt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Rdt = (du & 0xFFFF0000) | (dv >> 16);
}
Rx <<= 16;
Rg <<= 8;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
int32 tmp = FixedInvU(width);
int32 dgdx = tmp * (Rg - Lg) >> 15;
uint32 duv = Rt - Lt;
uint32 u = tmp * int16(duv >> 16);
uint32 v = tmp * int16(duv);
uint32 dtdx = (u & 0xFFFF0000) | (v >> 16);
int32 g = Lg;
uint32 t = Lt;
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
*ptr++ = gLightmap[(g >> 8 << 8) | gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
g += dgdx >> 1;
width--;
}
if (width & 1)
{
uint32 tmp = Rt - dtdx;
ptr[width - 1] = gLightmap[(Rg >> 8 << 8) | gTile[(tmp & 0xFF00) | (tmp >> 24)]];
}
#ifdef ALIGNED_LIGHTMAP
g += intptr_t(gLightmap);
#endif
width >>= 1;
while (width--)
{
#ifdef ALIGNED_LIGHTMAP
const uint8* LMAP = (uint8*)(g >> 8 << 8);
uint8 indexA = LMAP[gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
uint8 indexB = LMAP[gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
g += dgdx;
#else
uint8 indexA = gLightmap[(g >> 8 << 8) | gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
uint8 indexB = gLightmap[(g >> 8 << 8) | gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
g += dgdx;
#endif
#ifdef CPU_BIG_ENDIAN
*(uint16*)ptr = indexB | (indexA << 8);
#else
*(uint16*)ptr = indexA | (indexB << 8);
#endif
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
Lg += Ldg;
Rg += Rdg;
Lt += Ldt;
Rt += Rdt;
}
}
}
void rasterizeFTA_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
const uint8* ft_lightmap = &gLightmap[L->v.g << 8];
int32 Lh = 0, Rh = 0;
int32 Lx, Rx, Ldx = 0, Rdx = 0;
uint32 Lt, Rt, Ldt, Rdt;
Ldt = 0;
Rdt = 0;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
Lt = L->t.t;
if (Lh > 1)
{
int32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
uint32 duv = N->t.t - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Ldt = (du & 0xFFFF0000) | (dv >> 16);
}
Lx <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
Rt = R->t.t;
if (Rh > 1)
{
int32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
uint32 duv = N->t.t - Rt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Rdt = (du & 0xFFFF0000) | (dv >> 16);
}
Rx <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
uint32 tmp = FixedInvU(width);
uint32 duv = Rt - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
uint32 dtdx = (du & 0xFFFF0000) | (dv >> 16);
uint32 t = Lt;
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
uint8 p = gTile[(t & 0xFF00) | (t >> 24)];
if (p) {
*ptr = ft_lightmap[p];
}
ptr++;
t += dtdx;
width--;
}
if (width & 1)
{
uint32 tmp = Rt - dtdx;
uint8 p = gTile[(tmp & 0xFF00) | (tmp >> 24)];
if (p) {
ptr[width - 1] = ft_lightmap[p];
}
}
width >>= 1;
while (width--)
{
uint8 indexA = gTile[(t & 0xFF00) | (t >> 24)];
t += dtdx;
uint8 indexB = gTile[(t & 0xFF00) | (t >> 24)];
t += dtdx;
if (indexA && indexB)
{
indexA = ft_lightmap[indexA];
indexB = ft_lightmap[indexB];
#ifdef CPU_BIG_ENDIAN
*(uint16*)ptr = indexB | (indexA << 8);
#else
*(uint16*)ptr = indexA | (indexB << 8);
#endif
}/* else if (indexA) {
*(uint16*)ptr = (*(uint16*)ptr & 0xFF00) | ft_lightmap[indexA];
} else if (indexB) {
*(uint16*)ptr = (*(uint16*)ptr & 0x00FF) | (ft_lightmap[indexB] << 8);
}*/
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
Lt += Ldt;
Rt += Rdt;
}
}
}
void rasterizeGTA_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
rasterizeFTA(pixel, L, R);
}
void rasterizeSprite_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
// TODO
}
void rasterizeLineH_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
// TODO
}
void rasterizeLineV_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
// TODO
}
void rasterizeFillS_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
// TODO
}
#endif

1320
src/platform/32x/render.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
#include "common.h"
void sndInit()
{
// TODO
}
void sndInitSamples()
{
// TODO
}
void sndFreeSamples()
{
// TODO
}
void* sndPlaySample(int32 index, int32 volume, int32 pitch, int32 mode)
{
return NULL; // TODO
}
void sndPlayTrack(int32 track)
{
// TODO
}
void sndStopTrack()
{
// TODO
}
bool sndTrackIsPlaying()
{
return false; // TODO
}
void sndStopSample(int32 index)
{
// TODO
}
void sndStop()
{
// TODO
}
void sndFill(uint8* buffer, int32 count)
{
// TODO
}