Skip to content

Instantly share code, notes, and snippets.

@Ced2911
Created May 5, 2020 08:36
Show Gist options
  • Save Ced2911/4b5f03b9b1f93049b6d09a07e3c7a742 to your computer and use it in GitHub Desktop.
Save Ced2911/4b5f03b9b1f93049b6d09a07e3c7a742 to your computer and use it in GitHub Desktop.
/* Copyright 2014 Theo Berkau
This file is part of PseudoSaturn.
PseudoSaturn 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 2 of the License, or
(at your option) any later version.
PseudoSaturn 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 PseudoSaturn; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
Program that installs PseudoSaturn firmware to flash.
*/
#include <string.h>
#include <stdio.h>
#include <iapetus.h>
#include "version.h"
#define CODE_IN_LRAM __attribute__((section(".lram_data"))) __attribute__((noinline)) __attribute__((optimize("O1")))
static font_struct main_font;
#define CDWORKBUF ((void *)0x202C0000)
#define VDP1_TEXT_ADDR 0x20000
#define VDP1_PAL_ADDR 0x40000
u32 vdp_tile_start_address = 0x20000;
u32 vdp_tile_l_offset = 0;
u32 vdp_tile_u_offset = 0x8000;
//static uint16_t tiles_pixels[NB_TILE][8][8];
//static uint16_t * tile_addr = (uint16_t*)&tiles_pixels;
static volatile uint8_t *tile_addr = (volatile uint8_t *)(VDP1_TEXT_ADDR + VDP1_RAM);
static volatile uint16_t ***tiles_pixels = (volatile uint16_t ***)(VDP1_TEXT_ADDR + VDP1_RAM);
static volatile uint16_t *pal_addr = (volatile uint16_t *)(VDP1_PAL_ADDR + VDP1_RAM);
static volatile uint8_t *pal_addr_u8 = (volatile uint8_t *)(VDP1_PAL_ADDR + VDP1_RAM);
void vdp2_scroll_test_set_map(screen_settings_struct *settings, int which)
{
int i;
for (i = 0; i < 4; i++)
{
settings->map[i] = which;
}
}
void ps_init()
{
screen_settings_struct settings;
init_iapetus(RES_320x240);
// Setup a screen for us draw on
settings.is_bitmap = TRUE;
settings.bitmap_size = BG_BITMAP512x512;
settings.transparent_bit = 0;
settings.color = BG_256COLOR;
settings.special_priority = 0;
settings.special_color_calc = 0;
settings.extra_palette_num = 0;
settings.map_offset = 0;
settings.rotation_mode = 0;
settings.parameter_addr = 0x25E60000;
vdp_rbg0_init(&settings);
vdp_set_default_palette();
// Setup the default 8x8 1BPP font
main_font.data = font_8x8;
main_font.width = 8;
main_font.height = 8;
main_font.bpp = 1;
main_font.out = (u8 *)0x25E00000;
vdp_set_font(SCREEN_RBG0, &main_font, 1);
/*
u16 *pal = (u16 *)(VDP1_RAM + PAL_ADDR);
pal[0] = RGB32TO16(0xFF, 0xFF, 0xFF) | 0x8000;
pal[1] = RGB32TO16(0xFF, 0xFF, 0xFF) | 0x8000;
pal[9] = RGB32TO16(0xFF, 0, 0) | 0x8000;
*/
settings.is_bitmap = FALSE;
settings.bitmap_size = BG_BITMAP512x256;
settings.transparent_bit = 0;
settings.color = BG_16COLOR; //BG_256COLOR;
//settings.color = BG_256COLOR;
settings.special_priority = 0;
settings.special_color_calc = 0;
settings.extra_palette_num = 0;
settings.map_offset = 0;
settings.rotation_mode = 0;
settings.parameter_addr = 0;
settings.char_size = 0;
settings.plane_size = 0;
vdp2_scroll_test_set_map(&settings, 0);
vdp_nbg0_init(&settings);
// 16 bit color
// VDP2_REG_RAMCTL = (VDP2_REG_RAMCTL & 0xCFFF) | (2 << 12);
// Display everything
vdp_disp_on();
}
#define GTMCommandLongTileIdx 0 // data -> tile index (24 bits); palette index (8 bits)
#define GTMCommandLoadPalette 1 // data -> palette index (8 bits); palette format (8 bits) (00: RGBA32); RGBA bytes (32bits)
// new commands here
#define GTMCommandFrameEnd 28 // commandBits bit 0 -> keyframe end
#define GTMCommandTileset 29 // data -> start tile (32 bits); end tile (32 bits); indexes per tile (64 bytes); commandBits -> indexes bit count
#define GTMCommandSetDimensions 30 // data -> height in tiles (16 bits); width in tiles (16 bits); frame length in nanoseconds (32 bits); tile count (32 bits);
#define GTMCommandExtendedCommand 31 // data -> custom commands, proprietary extensions, ...; commandBits -> extended command index
#define GTMCommandShortTileIdxStart 32 // short tile index #0 ...; commandBits: palette index (3 bits); V mirror (1 bit); H mirror (1 bit)
#define GTMCommandShortTileIdxEnd 1919 // ... short tile index #1887
#define GTMCommandSkipBlockStart 1920 // skipping 128 tiles ...
#define GTMCommandSkipBlockEnd 2047 // ... skipping 1 tile
#define CTileWidth (8)
#define CTMAttrBits (1 + 1 + 3) // HMir + VMir + PalIdx
#define CShortIdxBits (16 - CTMAttrBits)
typedef struct
{
uint16_t width;
uint16_t height;
uint32_t frame_length;
uint32_t tile_count;
uint32_t palette_size;
uint32_t tile_map_positon;
// file...
file_struct *gtm_file;
uint32_t file_size;
uint8_t *ptr;
uint8_t *frame_data;
uint32_t data_pos;
// saturn specific
uint16_t *palettes;
uint8_t *tiles;
} gtm_ctx;
void GTM_init(gtm_ctx *gtm_ctx,
file_struct *gtm_file,
uint8_t *file_fuffer)
{
gtm_ctx->ptr = file_fuffer;
gtm_ctx->frame_data = file_fuffer;
gtm_ctx->data_pos = 0;
gtm_ctx->tile_map_positon = 0;
// saturn specific
gtm_ctx->file_size = gtm_file->size;
gtm_ctx->gtm_file = gtm_file;
}
#define CD_BUF 1024 * 600
uint8_t GTM_readByte(gtm_ctx *gtm_ctx)
{
if (gtm_ctx->data_pos >= CD_BUF)
{
int ret = 0;
vdp_printf(&main_font, 10, 20, 15, "GTM_readByte read disc");
if ((ret = cdfs_read(gtm_ctx->ptr, CD_BUF, 1, gtm_ctx->gtm_file)) != IAPETUS_ERR_OK)
{
vdp_printf(&main_font, 10, 28, 15, "cdfs_read error %d ", ret);
while (1)
vdp_vsync();
}
vdp_printf(&main_font, 10, 28, 15, "ok");
gtm_ctx->data_pos = 0;
gtm_ctx->frame_data = gtm_ctx->ptr;
}
return gtm_ctx->frame_data[gtm_ctx->data_pos++];
}
uint16_t GTM_readU16(gtm_ctx *gtm_ctx)
{
//return GTM_readByte(gtm_ctx) | (GTM_readByte(gtm_ctx) << 8);
uint16_t d = *(uint16_t *)(gtm_ctx->frame_data + gtm_ctx->data_pos);
gtm_ctx->data_pos += 2;
return __builtin_bswap16(d);
}
uint32_t GTM_readU32(gtm_ctx *gtm_ctx)
{
// return GTM_readU16(gtm_ctx) | (GTM_readU16(gtm_ctx) << 16);
uint32_t d = *(uint32_t *)(gtm_ctx->frame_data + gtm_ctx->data_pos);
gtm_ctx->data_pos += 4;
return __builtin_bswap32(d);
}
uint16_t GTM_readCommand(gtm_ctx *gtm_ctx)
{
uint16_t v = GTM_readU16(gtm_ctx);
return v;
}
void GTM_drawTilemapItem(gtm_ctx *gtm_ctx, uint32_t idx, uint16_t attrs)
{
uint32_t base = 0x000000;
volatile u32 *p = (volatile u32 *)(VDP2_RAM + base);
uint32_t x = (gtm_ctx->tile_map_positon % gtm_ctx->width);
uint32_t y = (gtm_ctx->tile_map_positon / gtm_ctx->width);
int special_priority = 0;
int special_color = 0;
uint32_t tile_addr = vdp_tile_start_address;
uint16_t palette = ((attrs >> 2));
uint16_t tile = idx;
uint8_t flip = attrs & 3;
p[(y * 0x40) + x] =
(flip << 30) |
(special_priority << 29) |
(special_color << 28) |
(tile_addr >> 5) |
(tile) |
(palette << 16);
gtm_ctx->tile_map_positon++;
}
void decodeAllChr()
{
volatile uint8_t *vdp_dst = (volatile u8 *)(VDP2_RAM + vdp_tile_start_address);
for (int n = 0; n < 1024; n++)
{
for (int row = 0; row < 8; row++)
{
for (int column = 0; column < 8; column++)
{
vdp_dst[(n * 8 * 8) + (row * 8) + column] = n;
}
}
}
}
void debugPal(gtm_ctx *gtm_ctx)
{
decodeAllChr();
for (int i = 0; i < 1024; i++)
{
gtm_ctx->tile_map_positon = i;
GTM_drawTilemapItem(gtm_ctx, i, 0);
}
while (1)
{
vdp_vsync();
}
}
void debugTile(gtm_ctx *gtm_ctx)
{
for (int i = 0; i < 1024; i++)
{
gtm_ctx->tile_map_positon = i;
GTM_drawTilemapItem(gtm_ctx, i, 0);
}
while (1)
{
vdp_vsync();
}
}
uint8_t GTM_decodeFrame(gtm_ctx *gtm_ctx)
{
static uint16_t l = 0;
uint32_t cmd = GTM_readCommand(gtm_ctx);
uint16_t cmd_0 = cmd & ((1 << CShortIdxBits) - 1);
uint16_t cmd_1 = cmd >> CShortIdxBits;
if (l > 240)
{
l = 0;
vdp_clear_screen(&main_font);
}
switch (cmd_0)
{
case GTMCommandSetDimensions:
{
gtm_ctx->width = GTM_readU16(gtm_ctx);
gtm_ctx->height = GTM_readU16(gtm_ctx);
gtm_ctx->frame_length = GTM_readU32(gtm_ctx); // / (1000 * 1000);
gtm_ctx->tile_count = GTM_readU32(gtm_ctx);
/*
vdp_printf(&main_font, 11, l += 8, 12, "gtm_ctx->width %d ", gtm_ctx->width);
vdp_printf(&main_font, 11, l += 8, 12, "gtm_ctx->height %d ", gtm_ctx->height);
vdp_printf(&main_font, 11, l += 8, 12, "gtm_ctx->frameLength %d ", gtm_ctx->frame_length);
vdp_printf(&main_font, 11, l += 8, 12, "gtm_ctx->tile_count %d ", gtm_ctx->tile_count);
while (1)
{
vdp_vsync();
}
*/
break;
}
case GTMCommandTileset:
{
uint32_t start = GTM_readU32(gtm_ctx);
uint32_t end = GTM_readU32(gtm_ctx);
gtm_ctx->palette_size = 1 << cmd_1;
volatile uint8_t *dst = gtm_ctx->tiles + (start * CTileWidth * CTileWidth);
for (uint32_t tile = start; tile <= end; tile++)
{
for (uint32_t w = 0; w < (CTileWidth * CTileWidth) / 2; w++)
{
uint8_t dot_0 = GTM_readByte(gtm_ctx);
uint8_t dot_1 = GTM_readByte(gtm_ctx);
*dst++ = (dot_0 << 4) | dot_1;
}
}
// debugTile(gtm_ctx);
break;
}
case GTMCommandLoadPalette:
{
uint8_t palIdx = GTM_readByte(gtm_ctx);
uint8_t palFmt = GTM_readByte(gtm_ctx);
// vdp_printf(&main_font, 11, l += 8, 12, "palIdx %d ", palIdx);
volatile uint16_t *dst = gtm_ctx->palettes + (palIdx * gtm_ctx->palette_size);
//volatile uint32_t *dst = gtm_ctx->palettes + (palIdx * gtm_ctx->palette_size);
for (uint16_t i = 0; i < gtm_ctx->palette_size; i++)
{
uint8_t r = GTM_readByte(gtm_ctx);
uint8_t g = GTM_readByte(gtm_ctx);
uint8_t b = GTM_readByte(gtm_ctx);
uint8_t a = GTM_readByte(gtm_ctx);
*dst++ = RGB555(r >> 3, g >> 3, b >> 3);
//*dst++ = (r << 0) | (g << 8) | (b << 16);
}
break;
}
case GTMCommandLongTileIdx:
{
//debugPal(gtm_ctx);
uint32_t v = GTM_readU32(gtm_ctx);
GTM_drawTilemapItem(gtm_ctx, v & 0x00ffffff, (cmd_1 & 3) | ((v >> 22) & 0x3fc));
break;
}
case GTMCommandFrameEnd:
gtm_ctx->tile_map_positon = 0;
// vdp_printf(&main_font, 11, l += 8, 12, "GTMCommandFrameEnd %d ", cmd_1);
// for (int i = 0; i < 240; i++)
for (int i = 0; i < 8; i++)
vdp_vsync();
return -1;
break;
default:
if (cmd_0 >= GTMCommandShortTileIdxStart && cmd_0 <= GTMCommandShortTileIdxEnd)
{
GTM_drawTilemapItem(gtm_ctx, cmd_0 - GTMCommandShortTileIdxStart, cmd_1);
}
else if (cmd_0 >= GTMCommandSkipBlockStart && cmd_0 <= GTMCommandSkipBlockEnd)
{
gtm_ctx->tile_map_positon += GTMCommandSkipBlockEnd - cmd_0 + 1;
}
else
{
vdp_printf(&main_font, 10, 20, 15, "Undecoded command %d", cmd_0);
while (1)
{
vdp_vsync();
}
//console.error('Undecoded command @' + gtmdata_pos + ': ' + cmd + '\n');
}
break;
}
return 0;
}
extern uint8_t LRAM__start, LRAM__end, lram_ptr;
uint8_t *lram = (uint8_t *)0x00200000;
int main()
{
#if 0
uint8_t *src = &lram_ptr;
uint8_t *dst = &LRAM__start;
while (dst < &LRAM__end)
{
*dst++ = *src++;
}
#endif
file_struct gtm_file;
int ret;
ps_init();
vdp_printf(&main_font, 10, 0, 15, "Start", 0);
vdp_vsync();
if ((ret = cdfs_init(CDWORKBUF, 4096)) != IAPETUS_ERR_OK)
{
vdp_printf(&main_font, 11, 20, 15, "cdfs_init error %d ", ret);
vdp_vsync();
return ret;
}
if ((ret = cdfs_open("GUNDAM", &gtm_file)) != IAPETUS_ERR_OK)
{
vdp_printf(&main_font, 10, 20, 15, "cdfs_open error %d ", ret);
vdp_vsync();
return ret;
}
if ((ret = cdfs_read(lram, CD_BUF, 1, &gtm_file)) != IAPETUS_ERR_OK)
{
vdp_printf(&main_font, 10, 20, 15, "cdfs_read error %d ", ret);
vdp_vsync();
return ret;
}
//vdp_printf(&main_font, 10, 20, 15, "volatile uint8_t *vdp_dst = (volatile u8 *)(VDP2_RAM + vdp_tile_start_address);", 0);
//vdp_vsync();
volatile uint8_t *vdp_dst = (volatile u8 *)(VDP2_RAM + vdp_tile_start_address);
gtm_ctx gtm_ctx;
GTM_init(&gtm_ctx, &gtm_file, lram);
gtm_ctx.tiles = vdp_dst;
gtm_ctx.palettes = vdp2_cram;
if (0)
{
gtm_ctx.width = 10;
// dbg ...
decodeAllChr();
for (int i = 0; i < 16; i++)
{
gtm_ctx.tile_map_positon = i + 10;
GTM_drawTilemapItem(&gtm_ctx, i, 0);
}
gtm_ctx.tile_map_positon = 0;
}
if (0)
while (1)
{
vdp_vsync();
}
for (;;)
{
if (GTM_decodeFrame(&gtm_ctx) == -1)
{
}
if (gtm_ctx.data_pos >= gtm_ctx.file_size)
{
gtm_ctx.data_pos = 0;
}
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment