* some basic BG display code

* basic, frozen-in-time RTC
* power management device
This commit is contained in:
StapleButter 2017-01-20 01:18:30 +01:00
parent d7c1d2a2cd
commit 3e5e8f60c4
8 changed files with 460 additions and 18 deletions

View File

@ -106,7 +106,7 @@ void DMA::Start()
if ((Cnt & 0x00060000) == 0x00060000)
CurDstAddr = DstAddr;
printf("ARM%d DMA%d %08X %08X->%08X %d bytes %dbit\n", CPU?7:9, Num, Cnt, CurSrcAddr, CurDstAddr, RemCount*((Cnt & 0x04000000)?2:4), (Cnt & 0x04000000)?16:32);
//printf("ARM%d DMA%d %08X %08X->%08X %d bytes %dbit\n", CPU?7:9, Num, Cnt, CurSrcAddr, CurDstAddr, RemCount*((Cnt & 0x04000000)?2:4), (Cnt & 0x04000000)?16:32);
// TODO: NOT MAKE THE DMA INSTANT!!
if (!(Cnt & 0x04000000))

View File

@ -89,9 +89,11 @@ void GPU2D::Write16(u32 addr, u16 val)
{
case 0x000:
DispCnt = (DispCnt & 0xFFFF0000) | val;
printf("[L] DISPCNT=%08X\n", DispCnt);
return;
case 0x002:
DispCnt = (DispCnt & 0x0000FFFF) | (val << 16);
printf("[H] DISPCNT=%08X\n", DispCnt);
return;
case 0x008: BGCnt[0] = val; return;
@ -108,6 +110,7 @@ void GPU2D::Write32(u32 addr, u32 val)
switch (addr & 0x00000FFF)
{
case 0x000:
printf("DISPCNT=%08X\n", val);
DispCnt = val;
return;
}
@ -159,18 +162,40 @@ void GPU2D::DrawScanline(u32 line)
void GPU2D::DrawScanline_Mode1(u32 line, u16* dst)
{
u32 backdrop;
if (Num) backdrop = *(u16*)&GPU::Palette[0x400];
else backdrop = *(u16*)&GPU::Palette[0];
// TODO: color effect for backdrop
backdrop |= (backdrop<<16);
for (int i = 0; i < 256>>1; i++)
((u32*)dst)[i] = 0; // TODO: backdrop
((u32*)dst)[i] = backdrop;
switch (DispCnt & 0x7)
{
case 0:
//printf("disp %08X %04X %04X %04X %04X\n", DispCnt, BGCnt[0], BGCnt[1], BGCnt[2], BGCnt[3]);
for (int i = 3; i >= 0; i--)
{
// TODO other BGs
if ((BGCnt[3] & 0x3) == i)
{
if (DispCnt & 0x0800) DrawBG_Text_4bpp(line, dst, 3);
// todo: sprites
}
if ((BGCnt[2] & 0x3) == i)
{
if (DispCnt & 0x0400) DrawBG_Text_4bpp(line, dst, 2);
// todo: sprites
}
if ((BGCnt[1] & 0x3) == i)
{
if (DispCnt & 0x0200) DrawBG_Text_4bpp(line, dst, 1);
// todo: sprites
}
if ((BGCnt[0] & 0x3) == i)
{
DrawBG_Text_4bpp(line, dst, 0);
if (DispCnt & 0x0100) DrawBG_Text_4bpp(line, dst, 0);
// todo: sprites
}
}
@ -259,6 +284,7 @@ void GPU2D::DrawBG_Text_4bpp(u32 line, u16* dst, u32 bgnum)
}
//color = (i >> 4) + ((line >> 4) << 4);
//if (Num) color = 0;
if (color)
dst[i] = curpal[color];
xoff++;

51
NDS.cpp
View File

@ -25,6 +25,7 @@
#include "FIFO.h"
#include "GPU.h"
#include "SPI.h"
#include "RTC.h"
#include "Wifi.h"
// derp
@ -128,6 +129,7 @@ void Init()
GPU::Init();
SPI::Init();
RTC::Init();
Reset();
}
@ -248,6 +250,7 @@ void Reset()
GPU::Reset();
SPI::Reset();
RTC::Reset();
Wifi::Reset();
memset(SchedBuffer, 0, sizeof(SchedEvent)*SCHED_BUF_LEN);
@ -1022,6 +1025,7 @@ void ARM9Write16(u32 addr, u16 val)
void ARM9Write32(u32 addr, u32 val)
{
if (addr == ARM9->R[15]) printf("!!!!!!!!!!!!9999 %08X %08X\n", addr, val);
if (addr == 0x023549F0) printf("%08X STATE=%08X\n", ARM9->R[15], val);
if (addr < ARM9ITCMSize)
{
*(u32*)&ARM9ITCM[addr & 0x7FFF] = val;
@ -1203,6 +1207,7 @@ u32 ARM7Read32(u32 addr)
void ARM7Write8(u32 addr, u8 val)
{
if (addr==0x3807764) printf("DERP! %02X %08X\n", val, ARM7->R[15]);
if (addr==0x27FFCE4) printf("FIRMWARE STATUS8 %04X %08X\n", val, ARM7->R[15]);
switch (addr & 0xFF800000)
{
case 0x02000000:
@ -1240,6 +1245,8 @@ void ARM7Write16(u32 addr, u16 val)
{
if (addr == ARM7->R[15]) printf("!!!!!!!!!!!!7777 %08X %04X\n", addr, val);
if (addr==0x3807764) printf("DERP! %04X %08X\n", val, ARM7->R[15]);
if (addr==0x27FF816) printf("RTC STATUS %04X %08X\n", val, ARM7->R[15]);
if (addr==0x27FFCE4) printf("FIRMWARE STATUS %04X %08X\n", val, ARM7->R[15]);
switch (addr & 0xFF800000)
{
case 0x02000000:
@ -1280,7 +1287,7 @@ void ARM7Write16(u32 addr, u16 val)
void ARM7Write32(u32 addr, u32 val)
{
if (addr == ARM7->R[15]) printf("!!!!!!!!!!!!7777 %08X %08X\n", addr, val);
if (addr==0x27FFCE4) printf("FIRMWARE STATUS32 %08X %08X\n", val, ARM7->R[15]);
switch (addr & 0xFF800000)
{
case 0x02000000:
@ -1689,7 +1696,7 @@ void ARM9IOWrite32(u32 addr, u32 val)
return;
case 0x04000208: IME[0] = val & 0x1; return;
case 0x04000210: IE[0] = val; return;
case 0x04000210: IE[0] = val; if (val&~0x000F0F7D)printf("unusual IRQ %08X\n",val);return;
case 0x04000214: IF[0] &= ~val; return;
case 0x04000240:
@ -1734,7 +1741,7 @@ u8 ARM7IORead8(u32 addr)
{
switch (addr)
{
case 0x04000138: return 0; // RTC shit
case 0x04000138: return RTC::Read() & 0xFF;
case 0x040001C2: return SPI::ReadData();
@ -1749,6 +1756,7 @@ u8 ARM7IORead8(u32 addr)
//Halt();
//return 0;
}
if (addr >= 0x04000400 && addr < 0x04000520)
{
// sound I/O
@ -1779,7 +1787,7 @@ u16 ARM7IORead16(u32 addr)
case 0x04000136: return KeyInput >> 16;
case 0x04000134: return 0x8000;
case 0x04000138: return 0; // RTC shit. TODO!!
case 0x04000138: return RTC::Read();
case 0x04000180: return IPCSync7;
case 0x04000184:
@ -1803,6 +1811,12 @@ u16 ARM7IORead16(u32 addr)
case 0x04000504: return _soundbias;
}
if (addr >= 0x04000400 && addr < 0x04000520)
{
// sound I/O
return 0;
}
printf("unknown ARM7 IO read16 %08X %08X\n", addr, ARM9->R[15]);
return 0;
}
@ -1865,6 +1879,12 @@ u32 ARM7IORead32(u32 addr)
case 0x04100010: return ROMReadData(1);
}
if (addr >= 0x04000400 && addr < 0x04000520)
{
// sound I/O
return 0;
}
printf("unknown ARM7 IO read32 %08X\n", addr);
return 0;
}
@ -1873,8 +1893,7 @@ void ARM7IOWrite8(u32 addr, u8 val)
{
switch (addr)
{
case 0x04000138:
return;
case 0x04000138: RTC::Write(val, true); return;
case 0x040001A0:
ROMSPIControl &= 0xFF00;
@ -1912,6 +1931,12 @@ void ARM7IOWrite8(u32 addr, u8 val)
return;
}
if (addr >= 0x04000400 && addr < 0x04000520)
{
// sound I/O
return;
}
printf("unknown ARM7 IO write8 %08X %02X\n", addr, val);
}
@ -1932,7 +1957,7 @@ void ARM7IOWrite16(u32 addr, u16 val)
case 0x04000134: return;printf("set debug port %04X %08X\n", val, ARM7Read32(ARM7->R[13]+4)); return;
case 0x04000138: return; // RTC shit. TODO
case 0x04000138: RTC::Write(val, false); return;
case 0x04000180:
IPCSync9 &= 0xFFF0;
@ -1985,6 +2010,12 @@ void ARM7IOWrite16(u32 addr, u16 val)
return;
}
if (addr >= 0x04000400 && addr < 0x04000520)
{
// sound I/O
return;
}
printf("unknown ARM7 IO write16 %08X %04X\n", addr, val);
}
@ -2052,6 +2083,12 @@ void ARM7IOWrite32(u32 addr, u32 val)
case 0x04000214: IF[1] &= ~val; return;
}
if (addr >= 0x04000400 && addr < 0x04000520)
{
// sound I/O
return;
}
printf("unknown ARM7 IO write32 %08X %08X\n", addr, val);
}

250
RTC.cpp Normal file
View File

@ -0,0 +1,250 @@
/*
Copyright 2016-2017 StapleButter
This file is part of melonDS.
melonDS 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.
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
*/
#include <stdio.h>
#include <string.h>
#include "RTC.h"
namespace RTC
{
u16 IO;
u8 Input;
u32 InputBit;
u32 InputPos;
u8 Output[8];
u32 OutputBit;
u32 OutputPos;
u8 CurCmd;
u8 StatusReg1;
u8 StatusReg2;
u8 Alarm1[3];
u8 Alarm2[3];
u8 ClockAdjust;
u8 FreeReg;
void Init()
{
}
void Reset()
{
Input = 0;
InputBit = 0;
InputPos = 0;
memset(Output, 0, sizeof(Output));
OutputPos = 0;
CurCmd = 0;
StatusReg1 = 0;
StatusReg2 = 0;
memset(Alarm1, 0, sizeof(Alarm1));
memset(Alarm2, 0, sizeof(Alarm2));
ClockAdjust = 0;
FreeReg = 0;
}
void ByteIn(u8 val)
{
//printf("RTC IN: %02X\n", val);
if (InputPos == 0)
{
if ((val & 0xF0) == 0x60)
{
u8 rev[16] = {0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6};
CurCmd = rev[val & 0xF];
}
else
CurCmd = val;
if (CurCmd & 0x80)
{
switch (CurCmd & 0x70)
{
case 0x00: Output[0] = StatusReg1; break;
case 0x40: Output[0] = StatusReg2; break;
case 0x20:
// TODO: get actual system time
Output[0] = 0x16;
Output[1] = 0x01;
Output[2] = 0x19;
Output[3] = 0x03; // day of week. checkme
Output[4] = 0x06;
Output[5] = 0x30;
Output[6] = 0x30;
break;
case 0x60:
// TODO: get actual system time
Output[0] = 0x06;
Output[1] = 0x30;
Output[2] = 0x30;
break;
case 0x10:
if (StatusReg2 & 0x04)
{
Output[0] = Alarm1[0];
Output[1] = Alarm1[1];
Output[2] = Alarm1[2];
}
else
Output[0] = Alarm1[2];
break;
case 0x50:
Output[0] = Alarm2[0];
Output[1] = Alarm2[1];
Output[2] = Alarm2[2];
break;
case 0x30: Output[0] = ClockAdjust; break;
case 0x70: Output[0] = FreeReg; break;
}
}
InputPos++;
return;
}
switch (CurCmd & 0x70)
{
case 0x00:
if (InputPos == 1) StatusReg1 = val & 0x0E;
break;
case 0x40:
if (InputPos == 1) StatusReg2 = val;
if (StatusReg2 & 0x4F) printf("RTC INTERRUPT ON: %02X\n", StatusReg2);
break;
case 0x20:
// TODO: set time somehow??
break;
case 0x60:
// same shit
break;
case 0x10:
if (StatusReg2 & 0x04)
{
if (InputPos <= 3) Alarm1[InputPos-1] = val;
}
else
{
if (InputPos == 1) Alarm1[2] = val;
}
break;
case 0x50:
if (InputPos <= 3) Alarm2[InputPos-1] = val;
break;
case 0x30:
if (InputPos == 1) ClockAdjust = val;
break;
case 0x70:
if (InputPos == 1) FreeReg = val;
break;
}
InputPos++;
}
u16 Read()
{
//printf("RTC READ %04X\n", IO);
return IO;
}
void Write(u16 val, bool byte)
{
if (byte) val |= (IO & 0xFF00);
//printf("RTC WRITE %04X\n", val);
if (val & 0x0004)
{
if (!(IO & 0x0004))
{
// start transfer
Input = 0;
InputBit = 0;
InputPos = 0;
memset(Output, 0, sizeof(Output));
OutputBit = 0;
OutputPos = 0;
}
else
{
if (!(val & 0x0002)) // clock low
{
if (val & 0x0010)
{
// write
if (val & 0x0001)
Input |= (1<<InputBit);
InputBit++;
if (InputBit >= 8)
{
InputBit = 0;
ByteIn(Input);
Input = 0;
InputPos++;
}
}
else
{
// read
if (Output[OutputPos] & (1<<OutputBit))
IO |= 0x0001;
else
IO &= 0xFFFE;
OutputBit++;
if (OutputBit >= 8)
{
OutputBit = 0;
if (OutputPos < 7)
OutputPos++;
}
}
}
}
}
if (val & 0x0010)
IO = val;
else
IO = (IO & 0x0001) | (val & 0xFFFE);
}
}

35
RTC.h Normal file
View File

@ -0,0 +1,35 @@
/*
Copyright 2016-2017 StapleButter
This file is part of melonDS.
melonDS 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.
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
*/
#ifndef RTC_H
#define RTC_H
#include "types.h"
namespace RTC
{
void Init();
void Reset();
u16 Read();
void Write(u16 val, bool byte);
}
#endif

81
SPI.cpp
View File

@ -17,6 +17,7 @@
*/
#include <stdio.h>
#include <string.h>
#include "NDS.h"
#include "SPI.h"
@ -185,6 +186,80 @@ void Write(u8 val, u32 hold)
}
namespace SPI_Powerman
{
u32 Hold;
u32 DataPos;
u8 Index;
u8 Data;
u8 Registers[8];
u8 RegMasks[8];
void Init()
{
}
void Reset()
{
Hold = 0;
Index = 0;
Data = 0;
memset(Registers, 0, sizeof(Registers));
memset(RegMasks, 0, sizeof(RegMasks));
Registers[4] = 0x40;
RegMasks[0] = 0x7F;
RegMasks[1] = 0x01;
RegMasks[2] = 0x01;
RegMasks[3] = 0x03;
RegMasks[4] = 0x0F;
}
u8 Read()
{
return Data;
}
void Write(u8 val, u32 hold)
{
if (!hold)
{
Hold = 0;
}
if (hold && (!Hold))
{
Index = val;
Hold = 1;
Data = 0;
DataPos = 1;
return;
}
if (DataPos == 1)
{
if (Index & 0x80)
{
Data = Registers[Index & 0x07];
}
else
{
Registers[Index & 0x07] =
(Registers[Index & 0x07] & ~RegMasks[Index & 0x07]) |
(val & RegMasks[Index & 0x07]);
}
}
else
Data = 0;
}
}
namespace SPI
{
@ -197,6 +272,7 @@ u32 CurDevice;
void Init()
{
SPI_Firmware::Init();
SPI_Powerman::Init();
}
void Reset()
@ -204,6 +280,7 @@ void Reset()
CNT = 0;
SPI_Firmware::Reset();
SPI_Powerman::Reset();
}
@ -224,6 +301,7 @@ u8 ReadData()
switch (CNT & 0x0300)
{
case 0x0000: return SPI_Powerman::Read();
case 0x0100: return SPI_Firmware::Read();
default: return 0;
}
@ -237,8 +315,9 @@ void WriteData(u8 val)
switch (CNT & 0x0300)
{
case 0x0000: SPI_Powerman::Write(val, CNT&(1<<11)); break;
case 0x0100: SPI_Firmware::Write(val, CNT&(1<<11)); break;
default: printf("SPI to unknown device %04X %02X\n", CNT, val); break;
default: break;//printf("SPI to unknown device %04X %02X\n", CNT, val); break;
}
if (CNT & (1<<14))

View File

@ -28,6 +28,7 @@
</Compiler>
<Linker>
<Add option="-s" />
<Add library="C:/MinGW/lib/libgdi32.a" />
</Linker>
</Target>
</Build>
@ -52,10 +53,14 @@
<Unit filename="DMA.h" />
<Unit filename="FIFO.cpp" />
<Unit filename="FIFO.h" />
<Unit filename="GPU.cpp" />
<Unit filename="GPU.h" />
<Unit filename="GPU2D.cpp" />
<Unit filename="GPU2D.h" />
<Unit filename="NDS.cpp" />
<Unit filename="NDS.h" />
<Unit filename="RTC.cpp" />
<Unit filename="RTC.h" />
<Unit filename="SPI.cpp" />
<Unit filename="SPI.h" />
<Unit filename="Wifi.cpp" />

View File

@ -10,7 +10,7 @@
1481161027 c:\documents\sources\melonds\types.h
1484758082 source:c:\documents\sources\melonds\nds.cpp
1484868036 source:c:\documents\sources\melonds\nds.cpp
<stdio.h>
<string.h>
"NDS.h"
@ -20,9 +20,10 @@
"FIFO.h"
"GPU.h"
"SPI.h"
"RTC.h"
"Wifi.h"
1484754523 source:c:\documents\sources\melonds\arm.cpp
1484870885 source:c:\documents\sources\melonds\arm.cpp
<stdio.h>
"NDS.h"
"ARM.h"
@ -76,12 +77,13 @@
1480957111 c:\documents\sources\melonds\spi.h
1484524946 source:c:\documents\sources\melonds\spi.cpp
1484762789 source:c:\documents\sources\melonds\spi.cpp
<stdio.h>
<string.h>
"NDS.h"
"SPI.h"
1484758294 source:c:\documents\sources\melonds\gpu2d.cpp
1484870914 source:c:\documents\sources\melonds\gpu2d.cpp
<stdio.h>
<string.h>
"NDS.h"
@ -103,7 +105,7 @@
1484612398 c:\documents\sources\melonds\fifo.h
"types.h"
1484756268 source:c:\documents\sources\melonds\dma.cpp
1484762586 source:c:\documents\sources\melonds\dma.cpp
<stdio.h>
"NDS.h"
"DMA.h"
@ -120,3 +122,11 @@
1484709419 c:\documents\sources\melonds\gpu.h
"GPU2D.h"
1484848282 c:\documents\sources\melonds\rtc.h
"types.h"
1484870861 source:c:\documents\sources\melonds\rtc.cpp
<stdio.h>
<string.h>
"RTC.h"