NP2kai/io/pegc.c
2019-03-21 20:48:05 +09:00

335 lines
14 KiB
C
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "compiler.h"
#include "cpucore.h"
#include "pccore.h"
#include "iocore.h"
#include "memegc.h"
#include "vram.h"
// PEGC プレーンモード
// 関連: vram.c, vram.h, memvga.c, memvga.h
// 詳しくもないのに作ったのでかなりいい加減です。
// 改良するのであれば全部捨てて作り直した方が良いかもしれません
#ifdef SUPPORT_PEGC
//
REG16 MEMCALL pegc_memvgaplane_rd16(UINT32 address){
int i,j;
UINT16 ret = 0;
UINT8 bit;
UINT32 addr; // 画素単位の読み込み元アドレス
UINT8 src, dst, pat1, pat2; // ソースデータ、ディスティネーションデータ、パターンデータ1&2
UINT8 ropcode = 0; // ラスタオペレーション設定 E0108h bit0〜bit7
UINT8 ropmethod = 0; // 論理演算の方法を指定(パターンレジスタまたはカラーパレット) E0108h bit11,10
UINT8 ropupdmode = 0; // 1ならラスタオペレーションを使用 E0108h bit12
UINT8 planemask = 0; // プレーン書き込み禁止(0=許可, 1=禁止) E0104h
UINT32 pixelmask = 0; // ビット(画素)への書き込み禁止(0=禁止, 1=許可) E010Ch
UINT32 bitlength = 0; // ブロック転送ビット長(転送サイズ-1) E0110h
UINT32 srcbitshift = 0; // リード時のビットシフト数 E0112h
UINT8 shiftdir = 1; // シフト方向0:inc, 1:decE0108h bit9
UINT8 srccpu = 1; // 直前に読み取ったVRAMデータではなくCPUデータを使用するか E0108h bit8
// PEGCレジスタ読みだし
ropcode = LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0xff;
ropmethod = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 10) & 0x3;
ropupdmode = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 12) & 0x1;
planemask = vramop.mio2[PEGC_REG_PLANE_ACCESS];
pixelmask = LOADINTELDWORD(vramop.mio2 + PEGC_REG_MASK);
bitlength = LOADINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH) & 0x0fff;
srcbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT)) & 0x1f;
shiftdir = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 9) & 0x1;
srccpu = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 8) & 0x1;
// 画素単位のアドレス計算
addr = (address - 0xa8000) * 8;
addr += srcbitshift;
addr &= 0x80000-1; // 安全のため
if(!srccpu){
if(!shiftdir){
for(i=0;i<16;i++){
UINT32 addrtmp = (addr + i) & (0x80000-1); // 読み取り位置
UINT32 pixmaskpos = (1 << ((15-i+8)&0xf)); // 現在の画素に対応するpixelmaskのビット位置
UINT8 data = vramex[addrtmp];
// compare data
if((data ^ vramop.mio2[PEGC_REG_PALETTE1]) & ~planemask){
ret |= (1<<i);
}
// update last data
pegc.lastdata[i] = data;
// update pattern reg
if((LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 13) & 0x1){
for(j=7;j>=0;j--){
UINT16 regdata = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4);
regdata = (regdata & ~(1 << i)) | (((data >> j) & 0x1) << i);
STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4, regdata);
}
}
}
}else{
for(i=0;i<16;i++){
UINT32 addrtmp = (addr - i) & (0x80000-1); // 読み取り位置
UINT32 pixmaskpos = (1 << ((i/8)*8 + (7-(i&0x7)))); // 現在の画素に対応するvalueやpixelmaskのビット位置
UINT8 data = vramex[addrtmp];
// compare data
if((data ^ vramop.mio2[PEGC_REG_PALETTE1]) & ~planemask){
ret |= (1<<i);
}
// update last data
pegc.lastdata[i] = data;
// update pattern reg
if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x2000){
for(j=7;j>=0;j--){
UINT16 regdata = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4);
regdata = (regdata & ~(1 << i)) | (((data >> j) & 0x1) << i);
STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4, regdata);
}
}
}
}
}
pegc.lastdatalen += 16;
return ret;
}
void MEMCALL pegc_memvgaplane_wr16(UINT32 address, REG16 value){
int i,j;
UINT8 bit;
UINT32 addr; // 画素単位の書き込み先アドレス
UINT8 src, dst, pat1, pat2; // ソースデータ、ディスティネーションデータ、パターンデータ1&2
UINT8 ropcode = 0; // ラスタオペレーション設定 E0108h bit0〜bit7
UINT8 ropmethod = 0; // 論理演算の方法を指定(パターンレジスタまたはカラーパレット) E0108h bit11,10
UINT8 ropupdmode = 0; // 1ならラスタオペレーションを使用 E0108h bit12
UINT8 planemask = 0; // プレーン書き込み禁止(0=許可, 1=禁止) E0104h
UINT32 pixelmask = 0; // ビット(画素)への書き込み禁止(0=禁止, 1=許可) E010Ch
UINT32 bitlength = 0; // ブロック転送ビット長(転送サイズ-1) E0110h
UINT32 dstbitshift = 0; // ライト時のビットシフト数 E0112h
UINT8 shiftdir = 1; // シフト方向0:inc, 1:decE0108h bit9
UINT8 srccpu = 1; // 直前に読み取ったVRAMデータではなくCPUデータを使用するか E0108h bit8
// PEGCレジスタ読みだし
ropcode = LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0xff;
ropmethod = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 10) & 0x3;
ropupdmode = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 12) & 0x1;
planemask = vramop.mio2[PEGC_REG_PLANE_ACCESS];
pixelmask = LOADINTELDWORD(vramop.mio2 + PEGC_REG_MASK);
bitlength = LOADINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH) & 0x0fff;
dstbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT) >> 8) & 0x1f;
shiftdir = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 9) & 0x1;
srccpu = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 8) & 0x1;
// 画素単位のアドレス計算
addr = (address - 0xa8000) * 8;
addr += dstbitshift;
addr &= 0x80000-1; // 安全のため
// ???
bit = (addr & 0x40000)?2:1;
//if(!srccpu && pegc.remain!=0 && pegc.lastdatalen < 16){
// return; // 書き込み無視
//}
if(pegc.remain == 0){
// データ数戻す?
pegc.remain = (LOADINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH) & 0x0fff) + 1;
}
if(!shiftdir){
// とりあえずインクリメンタル
// メモ (なんかおかしい)
// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
// i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
// value → bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 bitF bitE bitD bitC bitB bitA bit9 bit8
// pixelmask→ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 bitF bitE bitD bitC bitB bitA bit9 bit8 planemask SRC,DST,PAT
// ↓ ↓
// plane0 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit0 bit0
// plane1 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit1 bit1
// plane2 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit2 bit2
// plane3 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit3 bit3
// plane4 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit4 bit4
// plane5 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit5 bit5
// plane6 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit6 bit6
// plane7 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit7 bit7
for(i=0;i<16;i++){
UINT32 addrtmp = (addr + i) & (0x80000-1); // 書き込み位置
UINT32 pixmaskpos = (1 << ((i/8)*8 + (7-(i&0x7)))); // 現在の画素に対応するvalueやpixelmaskのビット位置
if(pixelmask & pixmaskpos){ // 書き込み禁止チェック
// SRCの設定
if(srccpu){
// CPUデータを使う
src = (value & pixmaskpos) ? 0xff : 0x00;
}else{
// 直前に読み取ったVRAMデータを使う
src = pegc.lastdata[i];
}
// DSTの設定 現在のVRAMデータ取得
dst = vramex[addrtmp];
if(ropupdmode){
// ROP使用
vramex[addrtmp] = (vramex[addrtmp] & planemask); // 書き換えされる予定のビットを0にしておく
// PATの設定
if(ropmethod==0){
// パターンレジスタを使用
int col = 0;
for(j=7;j>=0;j--){
col |= (LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4) >> i) & 0x1;
col <<= 1;
}
pat1 = pat2 = col;
}else if(ropmethod==1){
// パレット2を使用
pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE2];
}else if(ropmethod==2){
// パレット1を使用
pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE1];
}else if(ropmethod==3){
// パレット1と2を使用
pat1 = vramop.mio2[PEGC_REG_PALETTE1];
pat2 = vramop.mio2[PEGC_REG_PALETTE2];
}
// ROP実行
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<7)) vramex[addrtmp] |= (src & dst & pat1) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<6)) vramex[addrtmp] |= (src & dst & ~pat1) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<5)) vramex[addrtmp] |= (src & ~dst & pat1) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<4)) vramex[addrtmp] |= (src & ~dst & ~pat1) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<3)) vramex[addrtmp] |= (~src & dst & pat2) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<2)) vramex[addrtmp] |= (~src & dst & ~pat2) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<1)) vramex[addrtmp] |= (~src & ~dst & pat2) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<0)) vramex[addrtmp] |= (~src & ~dst & ~pat2) & (~planemask);
}else{
// SRCの0に対してplanemask&DST, 1に対して~planemask|DST
vramex[addrtmp] = 0;
for(j=0;j<8;j++){
if(src & (1<<j)){
vramex[addrtmp] |= (~planemask | dst) & (1<<j);
}else{
vramex[addrtmp] |= (planemask & dst) & (1<<j);
}
}
}
// ???
vramupdate[LOW15(addrtmp >> 3)] |= bit;
}
pegc.remain--;
// 転送サイズチェック
if(pegc.remain == 0){
goto endloop; // 抜ける
}
}
}else{
for(i=0;i<16;i++){
UINT32 addrtmp = (addr - i) & (0x80000-1); // 書き込み位置
UINT32 pixmaskpos = (1 << ((i/8)*8 + (7-(i&0x7)))); // 現在の画素に対応するvalueやpixelmaskのビット位置
if(pixelmask & pixmaskpos){ // 書き込み禁止チェック
// SRCの設定
if(srccpu){
// CPUデータを使う
src = (value & pixmaskpos) ? 0xff : 0x00;
}else{
// 直前に読み取ったVRAMデータを使う
src = pegc.lastdata[i];
}
// DSTの設定 現在のVRAMデータ取得
dst = vramex[addrtmp];
if(ropupdmode){
// ROP使用
vramex[addrtmp] = (vramex[addrtmp] & planemask); // 書き換えされる予定のビットを0にしておく
// PATの設定
if(ropmethod==0){
// パターンレジスタを使用
int col = 0;
for(j=7;j>=0;j--){
col |= (LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4) >> i) & 0x1;
col <<= 1;
}
pat1 = pat2 = col;
}else if(ropmethod==1){
// パレット2を使用
pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE2];
}else if(ropmethod==2){
// パレット1を使用
pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE1];
}else if(ropmethod==3){
// パレット1と2を使用
pat1 = vramop.mio2[PEGC_REG_PALETTE1];
pat2 = vramop.mio2[PEGC_REG_PALETTE2];
}
// ROP実行
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<7)) vramex[addrtmp] |= (src & dst & pat1) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<6)) vramex[addrtmp] |= (src & dst & ~pat1) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<5)) vramex[addrtmp] |= (src & ~dst & pat1) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<4)) vramex[addrtmp] |= (src & ~dst & ~pat1) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<3)) vramex[addrtmp] |= (~src & dst & pat2) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<2)) vramex[addrtmp] |= (~src & dst & ~pat2) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<1)) vramex[addrtmp] |= (~src & ~dst & pat2) & (~planemask);
if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<0)) vramex[addrtmp] |= (~src & ~dst & ~pat2) & (~planemask);
}else{
// SRCの0に対してplanemask&DST, 1に対して~planemask|DST
vramex[addrtmp] = 0;
for(j=0;j<8;j++){
if(src & (1<<j)){
vramex[addrtmp] |= (~planemask | dst) & (1<<j);
}else{
vramex[addrtmp] |= (planemask & dst) & (1<<j);
}
}
}
// ???
vramupdate[LOW15(addrtmp >> 3)] |= bit;
}
pegc.remain--;
// 転送サイズチェック
if(pegc.remain == 0){
goto endloop; // 抜ける
}
}
}
endloop:
gdcs.grphdisp |= bit;
pegc.lastdatalen -= 16;
}
UINT32 MEMCALL pegc_memvgaplane_rd32(UINT32 address){
// TODO: 作る
return 0;
}
void MEMCALL pegc_memvgaplane_wr32(UINT32 address, UINT32 value){
// TODO: 作る
}
void pegc_reset(const NP2CFG *pConfig) {
ZeroMemory(&pegc, sizeof(pegc));
pegc.enable = np2cfg.usepegcplane;
(void)pConfig;
}
void pegc_bind(void) {
}
#endif