s

  • タグ:
  • タグはありません
/*
Super Real Marjong P3 static video emulator
*/
class p3_sprite_1 extends raster_image{
	m_visible_area = {x = 511, y = 28 – 1, width = 384 + 1, height = 224 + 1}
	m_charcter = null; m_map = null; m_color = null;
	function map_init(vram, charbank){
		local map = []
		for(local i = 0; i < 0x200; i++){
			local attr = {y_pos = 0, y_flip = 0, x_pos = 0, x_flip = 0, color = 0, charcter = 0, bank = 0}
			attr.y_pos = vram[i] ^ 0xff
			attr.charcter = vram[0x1000 + i]
			attr.x_pos = vram[0x1200 + i]
			attr.x_flip = vram[0x3000 + i] & 0x80 ? 0x1ff : 0
			attr.y_flip = vram[0x3000 + i] & 0x40 ? 0xff : 0
			attr.bank = onebit_move(vram[0x3000 + i], 5, 0)
			attr.charcter = attr.charcter | ((vram[0x3000 + i] & 0x1f) << 8)
			if(attr.bank != 0){
				attr.charcter = attr.charcter | ((charbank +1) << 13)
			}
			attr.color = vram[0x3200 + i] >>> 3
			attr.x_pos = attr.x_pos | onebit_move(vram[0x3200 + i], 0, 8)
			map.append(attr)
		}
		map.reverse() //render higher -> lower address
		return map
	}
	
	function color_init(rom){
		local color = []
		foreach(v in rom){
			local r = (v & 0x1f) << 3
			v = v >>> 5
			local g = (v & 0x1f) << 3
			v = v >>> 5
			local b = (v & 0x1f) << 3
			color.append(0xff000000 | (r << 16) | (g << 8) | b)
		}
		return color
	}
	constructor(pal, charcter, m, charbank){
		image_init(1<<9, 1<<8, 0x7f7f7f7f);
		transback_draw(0x7f3f3f3f)
		m_map = map_init(m, charbank)
		m_color = color_init(pal)
		m_charcter = charcter
	}
	function render16x16(s){
		for(local y = 0, d = 0; y < 16; y++){
		for(local x = 0; x < 16; x++){
			if(x == 0 || x == 8){
				d = m_charcter[s.charcter]
				s.charcter += 1
			}
			d = (d << 4) | (d >>> 28)
			if((d & 0xf) != 0){
				put(
					(s.x_pos + (x ^ s.x_flip)) & 0x1ff,
					(s.y_pos + (y ^ s.y_flip)) & 0xff,
					m_color[s.color | (d & 0xf)]
				)
			}
		}}
	}
	function render(){
		foreach(attr in m_map){
			local s = clone attr
			s.charcter = s.charcter << (3 + 2)
			s.color = s.color << 4
			render16x16(s)
		}
		rect_draw(m_visible_area)
	}
}
/*
pseudo nametable style sprite.

– 横2x縦16個のスプライトを並べて描画する。
– 描画開始番号から0までを順番に描画する。
– 描画座標は1単位で1つ設定し、他のスプライトは順番に並べる。
– バンクは設定できないらしい。
並べる順番:
 0  1
 2  3
 4  5
 (中略)
30 31

b200h + (unit number) << 4
7:0 描画単位開始 position x bit 7:0

b204h + (unit number) << 4
7:0 描画単位開始 position y bit 7:0

b301h
3:0 描画単位開始番号 (1:15, 0:disable, other:num – 1)

b302h
7:0 描画単位 x position bit8 for bit7:0 (bit number == unit number)

b303h
7:0 b302h の対象 bit15:8

c400h-c5ffh
7:0 charcter index bit 7:0

e400h-e5ffh
7   x flip
6   y flip
4:0 charcter index bit 12:8

e600h-e7ffh
7:3 color index

atrribute RAM address bit
m:9 each attribute table
8:5 2×16 block unit number
4:0 internal sprite number
*/
class p3_sprite_2x16 extends p3_sprite_1{
	m_visible_area = {x = 511, y = 13 – 1, width = 384 + 1, height = 224 + 1} //?
	function map_init(vram, charbank){
		local map = []
		local unitindex = vram[0x0301] & 0xf
		local unit_x_bit8 = vram[0x302] | (vram[0x303] << 8)
		if(unitindex == 1){
			unitindex = 15
		}else{
			unitindex–
		}
		
		local global_xy_a = 0x0200 | (unitindex << 4)
		while(unitindex >= 0){
			local global_y = vram[global_xy_a + 0] ^ 0xff
			local global_x = vram[global_xy_a + 4] | onebit_move(unit_x_bit8, unitindex, 8)
			//print(format("i:%d x:%03x y:%02x\n", unitindex, global_x, global_y))
			for(local i = 0, attr_base_a = unitindex << 5; i < 0x20; i++, attr_base_a++){
				local attr = {y_pos = global_y, y_flip = 0, x_pos = global_x, x_flip = 0, color = 0, charcter = 0, bank = 0}
				attr.x_flip = vram[attr_base_a + 0x3400] & 0x80 ? 0x1ff : 0
				attr.y_flip = vram[attr_base_a + 0x3400] & 0x40 ? 0xff : 0
				attr.charcter = (vram[attr_base_a + 0x3400] & 0x1f) << 8
				attr.charcter = attr.charcter | vram[attr_base_a + 0x1400]
				attr.color = (vram[attr_base_a + 0x3600] >>> 3)
				map.append(attr)
				if(i & 1){
					global_y += 16
					global_y = global_y & 0xff
					attr.x_pos += 16
					attr.x_pos = attr.x_pos & 0x1ff
				}
			}
			unitindex–;
			global_xy_a -= (1<<4)
		}
		return map
	}
}
/*
VRAM image is Z80 memory b000h-ffffh
*/
function p3_render(rompath, outfile)
{
	local color = fileio_load_be16(rompath + "color.bin")
	local charcter = fileio_load_be32(rompath + "spritechar.bin")
	local vram = fileio_load_8(rompath + "vram.bin")
	local v1 = p3_sprite_1(
		color, charcter, vram,
		(0x70 >>> 6) & 0x3 //ioport 0x40
	)
	v1.render()
	local v32 = p3_sprite_2x16(
		color, charcter, vram,
		0 //bank is not used
	)
	v32.render()
	v1.image_add_height(v32)
	v1.save(outfile)
}
/*
charcter ROM data bit
     bit3   2  1  0
set0 za0-08 06 04 02
set1 za0-07 05 03 01

charcter ROM address は set0 -> set1 の順番

charcter size 16×16
address assignments  -> reorder address
msb:5 charcter index |msb:5 charcter index    
4   y.offset 3       |4:1 y.offset 3:0
3   x.offset 3       |0   x.offset 3
2:0 y.offset 2:0     |
*/
function p3_charrom_decode(infile0, infile1, outfile)
{
	local chardata = romio_bit_8x4to32(infile0)
	chardata.extend(romio_bit_8x4to32(infile1))
	local dest = array(chardata.len(), 0)
	for(local index = 0; index < chardata.len() >>> 5; index++){
	for(local y = 0; y < 16; y++){
	for(local x = 0; x < 16; x += 8){
		local src_a = (
			(index << 5) | 
			onebit_move(y, 3, 4) | onebit_move(x, 3, 3) |
			(y & 0x7)
		)
		local dest_a = (
			(index << 5) | 
			(y << 1) | onebit_move(x, 3, 0)
		)
		dest[dest_a] = chardata[src_a]
	}}}
	fileio_save_be32(outfile, dest)
}