1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-01-14 07:29:51 +00:00
2016-01-14 13:57:54 +01:00

237 lines
4.6 KiB
C

// boot_rom.c
// Boot ROM for the Z80 system on a chip (SoC)
// (c) 2015 Till Harbaum
#include <stdio.h>
#include <string.h>
#include "pff.h"
#define BUFFERS 8
const BYTE animation[] = "|/-\\";
// space for 8 sectors
DWORD frames = 0;
WORD rptr = 0xffff;
BYTE rsec = 0;
BYTE ym_buffer[BUFFERS][512];
__sfr __at 0x10 PsgAddrPort;
__sfr __at 0x11 PsgDataPort;
// YM replay is happening in the interrupt
void isr(void) __interrupt {
BYTE i, *p;
if(frames) {
frames--;
// write all 14 psg sound registers
p = ym_buffer[rsec] + rptr;
// unrolled loop for min delay between register writes
PsgAddrPort = 0; PsgDataPort = *p++;
PsgAddrPort = 1; PsgDataPort = *p++;
PsgAddrPort = 2; PsgDataPort = *p++;
PsgAddrPort = 3; PsgDataPort = *p++;
PsgAddrPort = 4; PsgDataPort = *p++;
PsgAddrPort = 5; PsgDataPort = *p++;
PsgAddrPort = 6; PsgDataPort = *p++;
PsgAddrPort = 7; PsgDataPort = *p++;
PsgAddrPort = 8; PsgDataPort = *p++;
PsgAddrPort = 9; PsgDataPort = *p++;
PsgAddrPort = 10; PsgDataPort = *p++;
PsgAddrPort = 11; PsgDataPort = *p++;
PsgAddrPort = 12; PsgDataPort = *p++;
PsgAddrPort = 13;
if(*p != 255) PsgDataPort = *p++;
rptr += 16;
// one whole sector processed?
if(rptr == 512) {
rsec++;
rptr=0;
if(rsec == BUFFERS)
rsec = 0;
}
} else {
// not playing? mute all channels
for(i=0;i<16;i++) {
PsgAddrPort = i;
PsgDataPort = 0;
}
}
// re-enable interrupt
__asm
ei
__endasm;
}
extern unsigned char font[];
unsigned char cur_x=0, cur_y=0;
void putchar(char c) {
unsigned char *p;
unsigned char *dptr = (unsigned char*)(160*(8*cur_y) + 8*cur_x);
char i, j;
if(c < 32) {
if(c == '\r')
cur_x=0;
if(c == '\n') {
cur_y++;
cur_x=0;
if(cur_y >= 12)
cur_y = 0;
}
return;
}
if(c < 0) return;
p = font+8*(unsigned char)(c-32);
for(i=0;i<8;i++) {
unsigned char l = *p++;
for(j=0;j<8;j++) {
*dptr++ = (l & 0x80)?0xff:0x00;
l <<= 1;
}
dptr += (160-8);
}
cur_x++;
if(cur_x >= 20) {
cur_x = 0;
cur_y++;
if(cur_y >= 12)
cur_y = 0;
}
}
void cls(void) {
unsigned char i;
unsigned char *p = (unsigned char*)0;
for(i=0;i<100;i++) {
memset(p, 0, 160);
p+=160;
}
}
void ei() {
// set interrupt mode 1 and enable interrupts
__asm
im 1
ei
__endasm;
}
void die (FRESULT rc) {
printf("Fail rc=%u", rc);
for (;;) ;
}
void main() {
FATFS fatfs; /* File system object */
FRESULT rc;
UINT bytes_read;
BYTE i, wsec = 0;
ei();
cls();
puts(" << Z80 SoC >>");
printf("Mounting SD card...\n");
// not playing? mute all channels
for(i=0;i<16;i++) {
PsgAddrPort = i;
PsgDataPort = 0;
}
rc = pf_mount(&fatfs);
if (rc) die(rc);
// open song.ym
printf("Opening SONG.YM...\n");
rc = pf_open("SONG.YM");
if(rc == FR_NO_FILE) {
printf("File not found");
for(;;);
}
if (rc) die(rc);
// read file sector by sector
do {
// Wait while irq routine is playing and all sector buffers are
// full This would be the place where we'd be doing the main
// processing like running a game engine.
while((wsec == rsec) && frames);
rc = pf_read(ym_buffer[wsec], 512, &bytes_read);
// No song info yet? Read and analyse header!
if(!frames) {
// check for file header
if((ym_buffer[0][0] != 'Y')||(ym_buffer[0][1] != 'M')) {
printf("No YM file!\n");
for(;;);
}
printf("YM version: %.4s\n", ym_buffer[0]);
// we only support files that are not interleaved
if(ym_buffer[0][19] & 1) {
printf("No Interleave!\n");
for(;;);
}
// we don't support digi drums
if(ym_buffer[0][20] || ym_buffer[0][21]) {
printf("No Digidums!\n");
for(;;);
}
// skip Song name, Author name and Song comment
rptr = 34;
printf("%s\n", ym_buffer[0]+rptr);
while(ym_buffer[0][rptr]) rptr++; // song name
rptr++;
printf("%s\n", ym_buffer[0]+rptr);
while(ym_buffer[0][rptr]) rptr++; // author name
rptr++;
while(ym_buffer[0][rptr]) rptr++; // song comment
rptr++;
// extract frames
frames = 256l*256l*256l*ym_buffer[0][12] + 256l*256l*ym_buffer[0][13] +
256l*ym_buffer[0][14] + ym_buffer[0][15];
printf("Frames: %ld\n", frames);
}
// circle through the sector buffers
wsec++;
if(wsec == BUFFERS)
wsec = 0;
// do some animation
printf("%c\r", animation[wsec&3]);
// do this until all sectors are read
} while((!rc) && (bytes_read == 512));
if (rc) die(rc);
printf("done.\n");
while(1);
}