スパカセROMライタのソース


/* Name: main.c

* Author: <insert your name here>

* Copyright: <insert your copyright message here>

* License: <insert your license reference here>

avrdude -p m328p -c avrispmkII -P usb -U flash:w:main.hex:i

*/

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include <avr/pgmspace.h>

PROGMEM const char mes_hello[]="SCV MONITOR ver0.2\n";

PROGMEM const char mes_xstart[]="XMODEM receive\n";

PROGMEM const char mes_xcancel[]="XMODEM aborted\n";

PROGMEM const char mes_done[]="XMODEM done\n";

PROGMEM const char mes_werror[]="Write Error\n";

PROGMEM const char mes_page[]="error! page is 0 to 7\n";

const short NOCHAR=-1;

const char BUFLENGTH=16;

int uart_test(void);

void uart_setting(void);

void sendchar(char data);

void messege(const char *mes);

void get_command();

short getchar(void);

void print(const char *mes);

void sendreturn();

void BIGLETTER(char *strp);

int hextoi(void);

int hextois(char data);

void printByte(unsigned char data);

void printShort(unsigned int data);

void printNibble(char data);

void phase(char *command);

void xmodem_down();

void dumphex(unsigned char *data,short dsize,unsigned short addr);

int blockWrite(unsigned char *data,short dsize,short addr);

int eraseChip();

void makeTable();

unsigned char rom_read(unsigned short addr);

void setOE(unsigned char x);

void setWE(unsigned char x);

void setCE(unsigned char x);

void WE_pulse(void);

void setAddr(unsigned short addr);

void setPage(unsigned char p);

void busSelect(int bus);

void setData(unsigned char x);

unsigned char readData(void);

void testwrite(unsigned short addr,unsigned char value);

char combuf[16];

unsigned char xmbuf[128];

unsigned char rTable[256];

int sComCount;

int main(void)

{

/* insert your hardware initialization here */

CLKPR=0x80;

CLKPR=0x00; //set 8MHz 1/1

uart_setting();

busSelect(0);   //SCV

sComCount=0;

combuf[0]=0;

 

makeTable();

messege(mes_hello);

//printShort(0xABCD);

 

for(;;){

/* insert your main loop code here */

//uart_test();

sendchar('>');

get_command();

BIGLETTER(combuf);

busSelect(1);   //AVR

phase(combuf);

//print(combuf);

 

 

}

return 0;   /* never reached */

}

void phase(char *command)

{

short i;

unsigned short ad;

unsigned char v;

switch (command[0]) {

case 'X':

xmodem_down();

//blockWrite(xmbuf,128,0);

//dumphex(xmbuf,128);

sendreturn();

break;

case 'A':   // for debug

/*for(i=0;i<4;i++){

testwrite((unsigned short)i,0xa5);

}*/

testwrite(0x1004,0x45);

//for(i=0;i<128;i++){xmbuf[i]=i;}

//blockWrite( xmbuf,128,0x0000);

break;

case 'D':

sComCount=2;

ad=hextoi();

dumphex(xmbuf,128,ad);

sendreturn();

break;

case 'W':

sComCount=2;

ad=hextoi();

sComCount++;

v=hextoi();

testwrite(ad,v);

sendreturn();

break;

case 'P':

sComCount=2;

v=hextoi();

if ( (v & 7)==v){

setPage(v);

}else{

messege(mes_page);

}

sendreturn();

break;

case 'E':

eraseChip();

default:

break;

}

}

// XMODEM受信

// チェックサムは処理してないです

void xmodem_down()

{

short rdata;

short i;

unsigned char sector,xsector;

unsigned short romaddr;

romaddr=0;

xsector=255;

messege(mes_xstart);

while ( (rdata=getchar())==NOCHAR)

{

//_delay_ms(500);

sendchar(0x15); //NAK

}

while(1){

if (rdata == 0x04) {

sendchar(0x06); //ACK

messege(mes_done);

return;

}

if (rdata != 0x01) {

messege(mes_xcancel);

return;

}

while ( (rdata=getchar())==NOCHAR);

sector=(unsigned char)rdata;

while ( (rdata=getchar())==NOCHAR);

for (i=0;i<128;i++){

while ( (rdata=getchar())==NOCHAR);

xmbuf[i]=rdata;

if (xsector != sector){

testwrite(romaddr,rTable[rdata]);   //回路ミスでSCV側DBUS反転してるので対策

romaddr++;

}

}

xsector=sector;

while ( (rdata=getchar())==NOCHAR); //cksum

//blockWrite(xmbuf,128,romaddr);

//romaddr+=128;

sendchar(0x06); //ACK

while ( (rdata=getchar())==NOCHAR); //next status

}

}

void dumphex(unsigned char *data,short dsize,unsigned short addr)

{

char bytecount;

short ofst;

ofst=addr;

bytecount=0;

 

while(dsize>0)

{

if (bytecount==0){

sendreturn();

printShort((unsigned short)ofst);

sendchar(0x20);

}

printByte(rTable[rom_read(ofst)]);

//printByte(xmbuf[ofst]);

sendchar(0x20);

ofst++;

bytecount++;

if (bytecount>15){

bytecount=0;

}

dsize--;

}

}

void testwrite(unsigned short addr,unsigned char value)

{

unsigned char d;

setOE(1);

setWE(1);

setCE(0);

setAddr(0x0555);

setData(0xAA);

WE_pulse();

setAddr(0x0AAA);

setData(0x55);

WE_pulse();

setAddr(0x0555);

setData(0xA0);

WE_pulse();

setAddr(addr);

setData(value);

WE_pulse();

goto skip1;

setOE(0);

d=value & 0x80;

while (1) {

if ( (readData()& 0x80) ==d ){

break;

}

if (readData() & 0x20){

if ( (readData()& 0x80) ==d ){

break;

}else{

setOE(1);

setCE(1);

//messege(mes_werror);

return ;   //fail

}

 

}

}

skip1:

setOE(1);

setCE(1);

}

int blockWrite(unsigned char *data,short dsize,short addr)

{

short i;

unsigned char d;

setOE(1);

setWE(1);

setCE(0);

for (i=0;i<dsize;i++){

setAddr(0x0555);

setData(0xAA);

WE_pulse();

setAddr(0x0AAA);

setData(0x55);

WE_pulse();

setAddr(0x0555);

setData(0xA0);

WE_pulse();

setAddr(addr+i);

setData(data[i]);

WE_pulse();

 

//書き込み完了待ち(D7の反転を検出する)

setOE(0);

d=data[i] & 0x80;

while (1) {

if ( (readData()& 0x80) ==d ){

break;

}

if (readData() & 0x20){

if ( (readData()& 0x80) ==d ){

break;

}else{

setOE(1);

setCE(1);

return 0;   //fail

}

 

}

}

setOE(1);

}

setCE(1);

return (1);   //success

}

unsigned char rom_read(unsigned short addr)

{

setWE(1);

setCE(0);

setAddr(addr);

setOE(0);

return (readData());

}

void setOE(unsigned char x)

{

if (x){PORTC |= 4;DDRB=0xFF;}else{DDRB=0x00;PORTC &= 0xFB;}

}

void setWE(unsigned char x)

{

if (x){PORTC |= 2;}else{PORTC &= 0xFD;}

}

void setCE(unsigned char x)

{

if (x==0){PORTC |= 1;}else{PORTC &= 0xFE;}

}

void WE_pulse(void)

{

PORTC &= 0xFD;

PORTC |= 2;

}

void setAddr(unsigned short addr)

{

setOE(1);

PORTB = addr & 0xff;

PORTC &= 0xF7;

PORTC |= 8;

PORTB = addr >>8;

PORTC &= 0xEF;

PORTC |= 0x10;

}

void setPage(unsigned char p)

{

PORTD = (PORTD & 0xE3) | (p<<2);

}

void busSelect(int bus)

{

if (bus==0){ //SCV

DDRC = (DDRC & 0xC0) | 0x38;

PORTC = (PORTC & 0xc0 ) | 0x3E;

DDRB=0;

}else{ //AVR

DDRC = (DDRC & 0xC0) | 0x3F;

PORTC = (PORTC & 0xc0 ) | 0x1F;

DDRB=0;

}

}

int eraseChip()

{

setOE(1);

setWE(1);

setCE(0);

 

setAddr(0x555);

setData(0xAA);

WE_pulse();

setAddr(0xAAA);

setData(0x55);

WE_pulse();

setAddr(0x555);

setData(0x80);

WE_pulse();

setAddr(0x555);

setData(0xAA);

WE_pulse();

setAddr(0xAAA);

setData(0x55);

WE_pulse();

setAddr(0x555);

setData(0x10);

WE_pulse();

/*

* [DQ7ポーリング]

* DQ7 == 0 チップ消去進行中

* DQ7 == 1 チップ消去完了

*/

setOE(0);

while ((readData() & 0x80) == 0)

; // @TODO タイムアウト処理

setOE(1);

 

setCE(1);

return 1;

}

void makeTable()

{

int i;

unsigned char v;

for (i=0;i<256;i++){

v=(i&128)?1:0;

v|=(i&64)?2:0;

v|=(i&32)?4:0;

v|=(i&16)?8:0;

v|=(i&8)?16:0;

v|=(i&4)?32:0;

v|=(i&2)?64:0;

v|=(i&1)?128:0;

rTable[i]=v;

}

}

void setData(unsigned char x)

{

PORTB=x;

}

unsigned char readData(void)

{

return(PINB);

}

void uart_setting(void)

{

unsigned char data = 0;  //受信したデータを格納

 

//送受信有効の場合、ポートD方向レジスタ(DDRD)のDDD1の値に拘らずRX/TXとして設定されます。

DDRD = 0b11111100;       //portD : 0,1:UART 2,3,4:BANK 5:LED 6,7:NC

DDRB = 0b00000000;      //portB : 0-7 DATA

DDRC = 0b00111111;      //portC :0 ROM_CS 1:WE 2:OR 3:ALCK 4:AHCK 5:574OE 6:ISP_RESET

PORTD = 0b00000000;

PORTC = 0b00111110;

 

UBRR0 = 51;   //ボーレート9600 @8MHz

 

UCSR0A = 0b00000000;    //受信すると10000000になる

//送信有効になると00100000になる

 

UCSR0B = 0b00011000;    //送受信有効

UCSR0C = 0b00000110;    //データ8bit

//非同期,パリティなし

//Stop 1bit

 

//sei(); /* enable grobal interrupt */

return;

}

ISR (USART_RX_vect)

{

unsigned char data = 0;

data = UDR0;

if (sComCount<8){

combuf[sComCount++]=data;

combuf[sComCount]=0;

}

}

void messege(const char *mes)

{

//mes must be flash

char data=1;

while (data){

data=pgm_read_byte(mes++);

sendchar(data);

if (data==10){

sendchar(13);

}

}

 

}

void print(const char *mes)

{

//mes must be flash

char data=1;

while (data){

data=*mes++;

if (data!=0){

sendchar(data);

}

}

 

}

void BIGLETTER(char *strp)

{

char data=1;

int cc=0;

while (data) {

data=strp[cc];

if ((data>='a')&&(data<='z')){

strp[cc]=strp[cc]-0x20;

}

cc++;

}

}

void sendchar(char data)

{

while( !(UCSR0A & 0b00100000) );

UDR0 = data;

}

void sendreturn(void)

{

sendchar(13);

sendchar(10);

}

int hextoi(void)

{

int res=0;

char data;

data=hextois(combuf[sComCount]);

if (data==-1) return(-1);

res=data;

while (data!=-1) {

sComCount++;

data=hextois(combuf[sComCount]);

if (data>=0) {res= (res<<4) | data;}

}

return(res);

}

void printByte(unsigned char data)

{

printNibble(data >>4 );

printNibble(data & 0x0f);

}

void printShort(unsigned int data)

{

printNibble(data >>12 );

printNibble((data>>8) & 0x0f);

printNibble((data>>4) & 0x0f);

printNibble(data & 0x0f);

}

void printNibble(char data)

{

if (data < 10) {

sendchar(data+'0');

}else{

sendchar(data-10+'A');

}

}

int hextois(char data)

{

int res=-1;

if ((data>='0')&&(data<='9')){res=data-'0';}

if ((data>='a')&&(data<='f')){res=data-'a'+10;}

if ((data>='A')&&(data<='F')){res=data-'A'+10;}

return(res);

}

short getchar(void)

{

short data;

if (UCSR0A & 0b10000000) {

data=(short)UDR0;

}else{

data=NOCHAR;

}

return(data);

}

void get_command()

{

int ccount=0;

short data=0;

while(data!=13){

data=getchar();

switch (data) {

case -1:

break;

case 13:

sendchar(13);

sendchar(10);

break;

case 8:

if (ccount != 0){

combuf[ccount-1]=0;

ccount--;

sendchar(data);

}

break;

 

default:

if (ccount < BUFLENGTH ){

if (data>31){

combuf[ccount++]=data;

combuf[ccount]=0;

sendchar(data);

}

}

break;

}

}

}

int uart_test(void)

{

unsigned char data = 0;  //受信したデータを格納

 

//送受信有効の場合、ポートD方向レジスタ(DDRD)のDDD1の値に拘らずRX/TXとして設定されます。

DDRD = 0b11111100;       //portD : 0,1pin以外出力

PORTD = 0b00000000;

 

UBRR0 = 51;   //ボーレート9600 @8MHz

 

UCSR0A = 0b00000000;    //受信すると10000000になる

//送信有効になると00100000になる

 

UCSR0B = 0b00011000;    //送受信有効

UCSR0C = 0b00000110;    //データ8bit

//非同期,パリティなし

//Stop 1bit

 

while(1){

//受信するまで待つ

while( !(UCSR0A & 0b10000000) );  //0ならループ

data = UDR0;  //受信したデータを格納

 

//受信できたかを確認するために受信データを返す

//送信できるまで待つ

while( !(UCSR0A & 0b00100000) );  //0ならループ

UDR0 = data;  //受信したデータを送信

}

 

return 0;

}

新刊「スーパーカセットビジョンでHELLO WORLD」リスト公開

新刊「スーパーカセットビジョンでHELLO WORLD」、ゲームレジェンドで頒布したのですが開始40分ぐらいで完売してしまいました。お求めになれなかった皆様、申し訳ありません。

ソースリストのご要望がありましたので、こちらで公開いたします。なお、7801の対応アセンブラは存在を知りませんのでこれがそのまま通るアセンブラは無いと思います。ハンドアセンブルの結果として参考にしてください。

スーパーカセットビジョン HELLO WORLD
8000 48       DB 'H'
8001 48 24    DI
8003 34 00 34 LXI H,3400H
8006 69 C9    MVI A,C9H 
8008 3B       STAX H
8009 69 F0    MVI A,F0H
800B 32       INX H
800C 3B       STAX H
800D 69 FF    MVI A,FFH
800F 32       INX H
8010 3B       STAX H
8011 69 F1    MVI A,F1H
8013 32       INX H
8014 3B       STAX H
8015 86       CALT 008CH
8016 34 40 80 LXI H,8040H
8019 24 43 30 LXI D,3043H
loop1:
801C 2D       LDAX H+
801D 3C       STAX D+
801E 77 00    EQI A,0
8020 FB       JR -5 ;loop1
 ;BEEP 
8021 34 00 36 LD H,03600H
8024 7F B0    CALF 0FB0H
8026 FF       JR -1 ;-1 
8040 DB "HELLO WORLD SCV",0
END

ゲームレジェンド

2016/11/6(日) 川口フレンディア4F

ゲームレジェンドに参加します

新刊は「スーパーカセットビジョンでHELLO WORLD」というコピー誌です

アセンブラも無い環境でスパカセプログラミングという内容です。あそぶ!ゲーム展Stage2のことも少しだけ。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88_2016_11_05_22_22