Skip to content

Commit

Permalink
Adding Dual screen support for DS port
Browse files Browse the repository at this point in the history
Signed-off-by: Giuliano Belinassi <[email protected]>
  • Loading branch information
giulianobelinassi committed May 22, 2024
1 parent 0668e88 commit 3cf407e
Show file tree
Hide file tree
Showing 16 changed files with 357 additions and 64 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ if(NDS)

set(ARCH "-mthumb -mthumb-interwork -mcpu=arm946e-s -mtune=arm946e-s")
set(CMAKE_C_FLAGS "${ARCH} ${CMAKE_C_CFLAGS} -fomit-frame-pointer -fno-rtti -fno-exceptions -ffast-math -fno-unwind-tables")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS} -DDS_RADAR_UPSCREEN")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -specs=ds_arm9.specs -mthumb -mthumb-interwork -Wl,-Map,vanilla.map")

# Link with those libraries.
Expand Down
7 changes: 6 additions & 1 deletion common/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ enum GBC_Enum
GBC_NONE = 0,
GBC_VIDEOMEM = 1,
GBC_VISIBLE = 2,
#ifdef _NDS
GBC_UPPERSCREEN = 4,
#endif
};

class VideoSurface;
Expand Down Expand Up @@ -105,5 +108,7 @@ unsigned Get_Video_Hardware_Capabilities();

void Wait_Vert_Blank();
void Set_DD_Palette(void* palette);

#ifdef DS_RADAR_UPSCREEN
void Set_DD_Upscreen_Palette(const void *palette);
#endif
#endif // VIDEO_H
146 changes: 105 additions & 41 deletions common/video_nds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,21 @@
* into screen, with the consequence of losing a few lines.
**/

extern "C" void memcpy32(void* dst, const void* src, unsigned int wdcount);
extern "C" {
void memcpy32(void* dst, const void* src, unsigned int wdcount);
void nocashWrite(const char *, int len);
}

void nocashPrintf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
char buf[128];
int len = vsnprintf(buf, 128, fmt, args);
va_end(args);
nocashWrite(buf, len);
}

void *tonccpy(void *dst, const void *src, size_t size);

/* Function used to pause the console for debugging. */
Expand All @@ -45,6 +59,7 @@ void DS_Pause(const char* format, ...)
// Background 3 identifier. Set on video initialization, and used on the seen
// surface buffer.
static int bg3;
static int bg3sub;

// Mark the status of zoom. True means we are zoomed in, false means we are
// zoomed out.
Expand Down Expand Up @@ -302,29 +317,69 @@ void On_VBlank()
Timer_VBlank();
}

bool Set_Video_Mode(int w, int h, int bits_per_pixel)
#ifdef DS_RADAR_UPSCREEN
static void Initialize_Upper_Screen(void)
{
// Allocate 128Kb for the console on the upper screen.
vramSetBankC(VRAM_C_SUB_BG_0x06200000);
videoSetModeSub(MODE_3_2D);

// Put pper screen into MODE5, which allows rotation and scaling on BG5
bg3sub = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0);

int scale_x = (256 * 256) / SCREEN_WIDTH;
int scale_y = (160 * 256) / SCREEN_HEIGHT;

bgSetRotateScale(bg3sub, 0, scale_x, scale_y);
bgSetScroll(bg3sub, 0, 0);

swiWaitForVBlank();
bgUpdate();

char *surface = (char *)bgGetGfxPtr(bg3sub);

for (int i = 0; i < 160; i++) {
for (int j = 0; j < 256; j++) {
if ((i + j) % 2 == 0)
surface[256 * i + j] = 98;
}
}
}
#else
static void Initialize_Upper_Console(void)
{
// Allocate memory for our console. This has to be static because it must
// persists when this function exit, even if only used here.
static PrintConsole cs0;

// Allocate 128Kb for the console on the upper screen. It is a bit
// overkill, but we got plenty of VRAM so far so it is OK.
vramSetBankC(VRAM_C_SUB_BG_0x06200000);
videoSetModeSub(MODE_0_2D);

// Initialize the console on the top screen.
consoleInit(&cs0, 0, BgType_Text4bpp, BgSize_T_256x256, 2, 0, false, true);
}
#endif

bool Set_Video_Mode(int w, int h, int bits_per_pixel)
{

// Only turns on the 2D engine. The 3D chip is unused and disabling it
// should save battery life.
powerOn(POWER_ALL_2D);

// If the ARM9 is set to 67MHz, set it to 133MHz now.
setCpuClock(true);

// Allocate 128Kb for the console on the upper screen. It is a bit
// overkill, but we got plenty of VRAM so far so it is OK.
vramSetBankC(VRAM_C_SUB_BG_0x06200000);
videoSetModeSub(MODE_0_2D);
#ifdef DS_RADAR_UPSCREEN
Initialize_Upper_Screen();
#else
Initialize_Upper_Console();
#endif

cpuStartTiming(0);

// Initialize the console on the top screen.
consoleInit(&cs0, 0, BgType_Text4bpp, BgSize_T_256x256, 2, 0, false, true);

// Setup what should run on a VBlank interrupt.
irqSet(IRQ_VBLANK, On_VBlank);

Expand Down Expand Up @@ -470,6 +525,20 @@ void Set_DD_Palette(void* palette)
HWCursor.Set_Cursor_Palette(BG_PALETTE);
}

void Set_Upperscreen_DD_Palette(const void *palette)
{
unsigned char r, g, b;

unsigned char* rcolors = (unsigned char*)palette;
for (int i = 0; i < 256; i++) {
r = (unsigned char)rcolors[i * 3] << 2;
g = (unsigned char)rcolors[i * 3 + 1] << 2;
b = (unsigned char)rcolors[i * 3 + 2] << 2;

BG_PALETTE_SUB[i] = RGB8(r, g, b);
}
}

void Wait_Blit(void)
{
}
Expand Down Expand Up @@ -526,48 +595,46 @@ void Update_HWCursor()
class VideoSurfaceNDS;
static VideoSurfaceNDS* frontSurface = nullptr;

// The hidden surface buffer.
static char HidSurfaceBuf[320 * 200];

#define ALIGNED(ptr, n) (((uintptr_t)(ptr) % (n)) == 0)

class VideoSurfaceNDS : public VideoSurface
{
public:
VideoSurfaceNDS(int w, int h, GBC_Enum flags)
: flags(flags)
, windowSurface(nullptr)
{
if (w == 320 && h == 200) {
if (flags & GBC_VISIBLE) {
if (flags & GBC_UPPERSCREEN) {
nocashWrite("Visible surface on upper screen\n", 100);
Pitch = w;
surface = (char*)bgGetGfxPtr(bg3sub);
} else {
// The DS renderer works as follows: we pass the background
// buffer in VRAM to the game's software engine, which draws
// things there. The background is a 512x256 surface, but
// only 512x200 pixels are used.

if (flags & GBC_VISIBLE) {
Pitch = 512;
surface = (char*)bgGetGfxPtr(bg3);
windowSurface = surface;
frontSurface = this;
} else {
// The hid surface will be allocated in main RAM. The game
// uses a software engine that memcpy the graphics, and in
// this case it is faster to allocate this in main RAM.
Pitch = 320;
surface = HidSurfaceBuf;
}
nocashWrite("Visible surface on botom screen\n", 100);
Pitch = 512;
surface = (char*)bgGetGfxPtr(bg3);
frontSurface = this;
}
} else {
swiWaitForVBlank();
printf("ERROR - Unsupported surface size\n");
while (1)
;
// The hid surface will be allocated in main RAM. The game
// uses a software engine that memcpy the graphics, and in
// this case it is faster to allocate this in main RAM.
Pitch = w;
surface = (char *)malloc(w*h);
nocashWrite("Hidden suface\n", 100);
}
}

virtual ~VideoSurfaceNDS()
{
if (frontSurface == this) {
frontSurface = NULL;
// Do not call free on surfaces that are allocated on VRAM.
if ((uintptr_t)surface < 0x06000000) {
// Deallocate surface in main RAM.
free(surface);
surface = NULL;
}
}

Expand Down Expand Up @@ -634,15 +701,13 @@ class VideoSurfaceNDS : public VideoSurface
}
} else {
short dma = 0;
int flushrange = 320*(h - 1) + w;

// Careful with alignment.
if (ALIGNED(src_ptr, 4) && ALIGNED(dst_ptr, 4)) {
if (src_in_main_ram) {
DC_FlushRange(src_ptr, flushrange);
}
if (src_in_main_ram)
DC_FlushRange(src_ptr, src_pitch*(h - 1) + w);
else if (dst_in_main_ram)
DC_FlushRange(dst_ptr, flushrange);
DC_FlushRange(dst_ptr, dst_pitch*(h - 1) + w);

// Unroll iterations:
short h_div = h / 4;
Expand Down Expand Up @@ -673,9 +738,9 @@ class VideoSurfaceNDS : public VideoSurface
} else if (ALIGNED(src_ptr, 2) && ALIGNED(dst_ptr, 2)) {

if (src_in_main_ram)
DC_FlushRange(src_ptr, flushrange);
DC_FlushRange(src_ptr, src_pitch*(h - 1) + w);
else if (dst_in_main_ram)
DC_FlushRange(dst_ptr, flushrange);
DC_FlushRange(dst_ptr, dst_pitch*(h - 1) + w);

// Unroll iterations:
short h_div = h / 4;
Expand Down Expand Up @@ -816,7 +881,6 @@ class VideoSurfaceNDS : public VideoSurface
private:
int Pitch;
char* surface;
char* windowSurface;
GBC_Enum flags;
};

Expand Down
5 changes: 5 additions & 0 deletions tiberiandawn/conquer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ void Main_Game(int argc, char* argv[])
*/
if (!Debug_Map) {
TotalLocks = 0;

if (Main_Loop()) {
break;
}
Expand Down Expand Up @@ -328,6 +329,10 @@ void Main_Game(int argc, char* argv[])
*/
Fade_Palette_To(BlackPalette, FADE_PALETTE_SLOW, NULL);
VisiblePage.Clear();
#ifdef DS_RADAR_UPSCREEN
void Clumsy_Upperscreen_Menu();
Clumsy_Upperscreen_Menu();
#endif

#ifndef DEMO
/*
Expand Down
12 changes: 11 additions & 1 deletion tiberiandawn/credits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ void CreditClass::Graphic_Logic(bool forced)
{
int factor = Get_Resolution_Factor();
int xx = SeenBuff.Get_Width() - (120 << factor);
int yy = 0;
if (forced || IsToRedraw) {

/*
Expand Down Expand Up @@ -117,8 +118,17 @@ void CreditClass::Graphic_Logic(bool forced)
factor ? TPF_GREEN12_GRAD | TPF_CENTER | TPF_USE_GRAD_PAL : TPF_6PT_GRAD | TPF_CENTER | TPF_NOSHADOW;
unsigned fore = factor ? 11 : WHITE;

#ifdef DS_RADAR_UPSCREEN
GraphicViewPortClass* oldpage = Set_Logic_Page(UpperHidBuff);
xx = 256 - (80 / 2);
yy = 160 - 8;
#endif
TabClass::Draw_Credits_Tab();
Fancy_Text_Print("%ld", xx, 0, fore, TBLACK, flags, Current);
Fancy_Text_Print("%ld", xx, yy, fore, TBLACK, flags, Current);

#ifdef DS_RADAR_UPSCREEN
Set_Logic_Page(oldpage);
#endif

IsToRedraw = false;
IsAudible = false;
Expand Down
9 changes: 9 additions & 0 deletions tiberiandawn/externs.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,15 @@ extern GraphicBufferClass ModeXBuff;
extern GraphicViewPortClass HidPage;
extern GraphicBufferClass LoResHidPage;
extern GraphicBufferClass SysMemPage;
#ifdef DS_RADAR_UPSCREEN
extern GraphicBufferClass UpperVisiblePage;
extern GraphicBufferClass UpperHiddenPage;
extern GraphicViewPortClass UpperHidBuff;
extern GraphicViewPortClass UpperSeenBuff;

extern void Set_Upperscreen_DD_Palette(const void *palette);

#endif
extern int MenuList[][8];
extern CountDownTimerClass FrameTimer;
extern CountDownTimerClass CountDownTimer;
Expand Down
7 changes: 7 additions & 0 deletions tiberiandawn/globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,13 @@ int MenuList[][8] = {
GraphicBufferClass VisiblePage;
GraphicBufferClass HiddenPage;

#ifdef DS_RADAR_UPSCREEN
GraphicBufferClass UpperVisiblePage;
GraphicBufferClass UpperHiddenPage;
GraphicViewPortClass UpperHidBuff(&UpperHiddenPage, 0, 0, 256, 160);
GraphicViewPortClass UpperSeenBuff(&UpperVisiblePage, 0, 0, 256, 160);
#endif

GraphicViewPortClass SeenBuff(&VisiblePage, 0, 0, GBUFF_INIT_WIDTH, GBUFF_INIT_HEIGHT);
GraphicBufferClass ModeXBuff;
GraphicViewPortClass HidPage(&HiddenPage, 0, 0, GBUFF_INIT_WIDTH, GBUFF_INIT_HEIGHT);
Expand Down
3 changes: 3 additions & 0 deletions tiberiandawn/gscreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,9 @@ void GScreenClass::Blit_Display(void)
#else //(0)
WWMouse->Draw_Mouse(&HidPage);
HidPage.Blit(SeenBuff, 0, 0, 0, 0, HidPage.Get_Width(), HidPage.Get_Height(), false);
#ifdef DS_RADAR_UPSCREEN
UpperHiddenPage.Blit(UpperVisiblePage, 0, 0, 0, 0, UpperHiddenPage.Get_Width(), UpperHiddenPage.Get_Height(), false);
#endif
#ifdef CHEAT_KEYS
Add_Current_Screen();
#endif
Expand Down
11 changes: 11 additions & 0 deletions tiberiandawn/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,11 @@ bool Init_Game(int, char*[])
Blit_Hid_Page_To_Seen_Buff();
}

#ifdef DS_RADAR_UPSCREEN
void Clumsy_Upperscreen_Menu(void);
Clumsy_Upperscreen_Menu();
#endif

Hide_Mouse();
Wait_Vert_Blank();
if (!Special.IsFromInstall) {
Expand All @@ -525,6 +530,7 @@ bool Init_Game(int, char*[])
}
}
}

Call_Back();

// malloc(2);
Expand Down Expand Up @@ -1395,6 +1401,11 @@ bool Select_Game(bool fade)
return (false);
}
CCDebugString("C&C95 - Scenario started OK.\n");

#ifdef DS_RADAR_UPSCREEN
UpperSeenBuff.Clear();
UpperHidBuff.Fill_Rect(0, 0, 256, 160, GREY);
#endif
}

/*
Expand Down
Loading

0 comments on commit 3cf407e

Please sign in to comment.