Copy Link
Add to Bookmark
Report

GP32 demo code (mummu)

sang's profile picture
Published in 
GP32
 · 9 months ago

Yet another stuuuupid demo.. featuring slightly modified crossfade (tm) routine by Costis (tm).. I was just experimenting some DMA and MMU stuff.

Btw the screen is 640x480x16bits and won't fit into BIOS provided memory area. Blah blah blah blah..

mummu.c

// DMA & MMU demo (c) 2002 Jouni 'Mr.Spiv' korhonen 
// Really simple & stuuuupid
//
// The 'crossfade' routine originally (c) Costis
// from his Crossfade-demo


#include "gpdef.h"
#include "gpstdlib.h"
#include "gpgraphic.h"
#include "gpmain.h"
#include "gpfont.h"
#include "gpmem.h"

#include <stdlib.h>
#include <string.h>

//

volatile long* tpal = (long*)0x14a00050;
volatile long* lcdcon1 = (long*)0x14a00000;
volatile long* lcdcon2 = (long*)0x14a00004;
volatile long* lcdcon3 = (long*)0x14a00008;
volatile long* lcdcon4 = (long*)0x14a0000c;
volatile long* lcdcon5 = (long*)0x14a00010;

volatile long* lcdaddr1 = (long*)0x14a00014;
volatile long* lcdaddr2 = (long*)0x14a00018;
volatile long* lcdaddr3 = (long*)0x14a0001c;
volatile long* hwpal = (long*)0x14a00400;

// dma0

volatile long* disrc0 = (long*)0x14600000;
volatile long* didst0 = (long*)0x14600004;
volatile long* dcon0 = (long*)0x14600008;
volatile long* dstat0 = (long*)0x1460000c;
volatile long* dcsrc0 = (long*)0x14600010;
volatile long* dcdst0 = (long*)0x14600014;
volatile long* dmasktrig0 = (long*)0x14600018;

//

extern unsigned char BK_Pic_c1[];
extern unsigned char BK_Pic_c2[];
extern long sin_tbl[]; // 256

//

#define FRAMEBUFFER_SIZE (640*480*2)

//

static unsigned short mempic1[640*480] = {0};
static unsigned short mempic2[640*480] = {0};

//
//
//

void waitline( int line ) {
while (line != ((*lcdcon1 >> 18) & 0x1ff) );
}

//
// DMA0 memory to memory copy routine..
// Note: size = number or words to copy.
//
// This DMA copy routine does not use interrupts to inform when the
// DMA has finished.. which is kinda lame. The caller must use the
// 'DMA0WaitEnd()' function to check/busywait to see when DMA has finished
// the data transfer.
//

void DMA0CopyStart( unsigned char *s, unsigned char *d, long size ) {
// Stop DMA0
*dmasktrig0 |= 0x04;

// Setup source...
// select system bus (AHB)
// select address increment
*disrc0 = (long)s;

// Setup destination...
// select system bus (AHB)
// select address increment
*didst0 = (long)d;

// DMA0 con..
*dcon0 = (0 << 30) | // demand mode
(1 << 29) | // DREQ & DACK are synched to HCLK (AHB)
(0 << 28) | // disable DMA0 int
(0 << 27) | // unit transfer
(1 << 26) | // whole servmode
(0x00 << 24) | // HWSRCSEL ?? not used
(0 << 23) | // sw request mode
(1 << 22) | // auto reload off
(0x02 << 20) | // data size == word
(size >> 2); // count..

// start DMA.. and don't wait for it to finish..
*dmasktrig0 = 0x03;
}

//

void DMA0WaitEnd( void ) {

// poll for end..

while ((*dstat0 >> 20) & 0x03);
}

//
//
//
//
//

void GpMain(void *arg)
{
unsigned char* framebuf;
unsigned char* framebuffer_strt;
unsigned char* framebuffer_stop;
long up,lo;
long ptr;
int m,n,i,j,k,l,xc,yc;

unsigned short *dst;
unsigned short *src;

//
// Allocate memory.. add 4KB extra to be sure there's enough
// memory to tolerate page size and alignment requirements
//
framebuf = (unsigned char*)gm_malloc(FRAMEBUFFER_SIZE+4096);

if (framebuf == NULL) {
// lamah..
GpAppExit();
}
// Ensure 4KB alignment..
framebuffer_strt = (unsigned char*)((long)(framebuf + 4095) & 0xfffff000);
framebuffer_stop = framebuffer_strt + FRAMEBUFFER_SIZE;

// Do the MMU mapping.. remember 4KB pages!
// for the mmu flags: 0xff2 -> no cache, no writeback

swi_mmu_change(framebuffer_strt,framebuffer_stop-1,0x00000ff2);

// copy & double to frame buffer

dst = mempic1;
src = (unsigned short*)BK_Pic_c1;

for (m = 0; m < 320; m++) {
for (n = 0; n < 240; n++) {
*dst++ = *src;
*dst++ = *src++;
}
for (n = 0; n < 480; n++) {
*dst = dst[-480];
dst++;
}
}

DMA0CopyStart( (unsigned char*)mempic1, framebuffer_strt, 640*480*2 );

// copy & double to mem buffer

dst = mempic2;
src = (unsigned short*)BK_Pic_c2;

for (m = 0; m < 320; m++) {
for (n = 0; n < 240; n++) {
*dst++ = *src;
*dst++ = *src++;
}
for (n = 0; n < 480; n++) {
*dst = dst[-480];
dst++;
}
}

DMA0WaitEnd();


// 320x240x16 screen mode, 0 pixel offscreen
// expects 33MHz HCLK

*lcdcon1 = ((3 << 8) | (0 << 7) | (3 << 5) | (12 << 1) | (0));
// CLKVAL=3, VNMODE=0, PNRMODE=TFT, BPPMODE=1100 (16bits), ENDID=0
*lcdcon2 = ((1 << 24) | (319 << 14) | (2 << 6) | 1);
// VBPD=1, LINEVAL=319, VFPD=2, VSPW=1
*lcdcon3 = ((6 << 19) | (239 << 8) | (2));
// HBPD=6, HOZVAL=239, HFPD=2
*lcdcon4 = ((0 << 24) | (0 << 16) | (4));
// PALADDEN=0, ADDVAL=0, HSPW=4
*lcdcon5 = ((1 << 10) | (1 << 9) | (1 << 8) | (0 << 7) | (0 << 6) | (0 << 4) | (0 << 2) | (1));
// INVVCLK=1, INVVLINE=1, INVVFRAME=1, INVVD=0, INVVDEN=0
// INVENDLINE=0, ENLEND=0, BSWP=0, HWSWP=1
*tpal = 0;

ptr = (long)framebuffer_strt;
*lcdaddr1 = ((ptr & 0x0fc00000) >> 1) | ((ptr & 0x3ffffe) >> 1);
*lcdaddr2 = ((ptr & 0x003ffffe) >> 1) + (240+240) * (319+1);

*lcdaddr3 = ((240 << 11) | (240));
// OFFSIZE=240, PAGEWIDTH=240 halfwords -> 240 pixels
//*lcdaddr3 = ((360 << 11) | (120));
// // OFFSIZE=240, PAGEWIDTH=240 halfwords -> 240 pixels

*lcdcon1 |= 1; // enable lcd

up = *lcdaddr1;
lo = *lcdaddr2;
n = 0;
m = 64;
i = 0;
j = 0;
k = 0;
xc = 0; yc = 0;

while ((GpKeyGet() & (GPC_VK_FL | GPC_VK_FR)) != (GPC_VK_FL | GPC_VK_FR)) {
unsigned short *bk0;
unsigned short *bk1;
unsigned short r,g,b,R,G,B;

dst = (unsigned short*)framebuffer_strt + k*480;
bk0 = dst;

if (k == 0) { yc = 0; }
if (j) {
bk1 = mempic2 + k*2*240;
} else {
bk1 = mempic1 + k*2*240;
}

for (l = 0, xc = 0; l < 480*20; l++) {
r=(*(bk0 + l) & 0xF800) >> 11;
g=(*(bk0 + l) & 0x7C0) >> 6;
b=(*(bk0 + l) & 0x3E) >> 1;
R=(*(bk1 + l) & 0xF800) >> 11;
G=(*(bk1 + l) & 0x7C0) >> 6;
B=(*(bk1 + l) & 0x3E) >> 1;

xc = 3;
if (r > R) r-=1; else if (r < R) r+=1; else xc--;
if (g > G) g-=1; else if (g < G) g+=1; else xc--;
if (b > B) b-=1; else if (b < B) b+=1; else xc--;
if (xc > 0) { yc++; }

*dst++ = ((r << 11) | (g<<6) | (b<<1));
}

waitline(2);
*lcdaddr1 = up + 480*sin_tbl[n] + sin_tbl[m];
*lcdaddr2 = lo + 480*sin_tbl[n] + sin_tbl[m];

waitline(1);

n = (n + 1) % 256;
m = (m + 1) % 256;
i = (i + 1) % 640;
k = (k + 20) % 640;

if (yc == 0) {
j ^= 1;
yc = 0;
}
}

// free memory & reboot
gm_free(framebuf);
GpAppExit();
}

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT