#include #include #include #include "z80-cpu.h" #include "z80-mon.h" _uchar *io_address; static _uchar memory[1<<16]; #define MEMORY_INIT_BYTE 0x0 /* also used for accessing unreadable memory */ static unsigned char empty = MEMORY_INIT_BYTE; struct port_map { bit virtuel; unsigned short offset; short port_no; unsigned char mask; unsigned short count; unsigned char *bankids; } ; static struct { unsigned char type; /* type=='-' means virtuel bank */ unsigned short log2_size; unsigned char *back_up; unsigned char mapped_from; /* relevant for virtuel bank only */ } bank[256]; static unsigned no_maps, delta; static bit all_readable; struct port_map *map; static unsigned char **address_map; /* map of bank_id's in current memory */ static unsigned char *mapped_from; /* reverse map of bank_id's */ static unsigned long access_type; /* holds two bits for each possible bank */ #ifdef NEEDED static void set_bank_port(unsigned char port_id, unsigned char value) { #ifdef OLD_STYLE FILE *fp; if (!(fp=fopen(Z80_PORTS,"r+b"))) return; fseek(fp,port_id,SEEK_SET); fwrite(&value,1,1,fp); fclose(fp); #endif } #endif #define MAX_NEST 2 /* unbelievable hardware if greater than 2 **/ static unsigned char * update_all_adress_maps(unsigned char bank_id) { unsigned i, j, t=0; unsigned char id, end=0; /* to prevent compiler warning uninitialization */ bool first=1; for (i=1<<16-delta;i--;) { bool update=0; if (address_map[i] == memory) continue; id=mapped_from[i]; for (j=0; bank[id].type=='-' && (!first || j < MAX_NEST); j++) { if (id == bank_id) { update= 1; if (!first) break; } id= bank[id].mapped_from; } if (update) { if (!first) address_map[i]= bank[end=id].back_up; else address_map[i]= bank[end].back_up; i *= 2; access_type &= ~(3<>delta; #ifdef NEEDED unsigned j; for (j=0;j= 0) /* different ports have equal offset!! */ set_bank_port((unsigned char)map[j].port_no,id); } #endif mapped_from[index]= id; address_map[index] = bank[id].back_up; index *= 2; access_type &= ~(3< no_maps || !map_no || map[map_no-1].port_no < 0) return; portno= map[map_no-1].port_no; for (i=0;i= 256) { sprintf(err_line,ERROR_BANK,k); error(0,err_line," invalid bank_id"); continue; } if (bank[id].type) { sprintf(err_line,ERROR_BANK,k); error(0,err_line," bank_id already defined"); continue; } if (delta && id < pre_id) { sprintf(err_line,ERROR_BANK,k); error(0,err_line," bank_id not ascending sorted"); continue; } if (1 != sscanf(tok3,"%u",&log2) || (log2 != 12 && log2 != 14)) { sprintf(err_line,ERROR_BANK,k); error(0,err_line," invalid log2_size"); continue; } if (delta && log2 != delta) { sprintf(err_line,ERROR_BANK,k); error(0,err_line," different bank sizes"); continue; } strcpy(filename+b,tok4); if (tok4[0] == '-' && tok4[1] == '\0') rom_fp = NULL; else if (tok1[0]=='-') { sprintf(err_line,ERROR_BANK,k); error(0,err_line," virtuel bank has bank file"); continue; } else if (!(rom_fp = fopen(filename,"r"))) { char err_msg[64]; sprintf(err_line,ERROR_BANK,k); sprintf(err_msg," can't open bank file %63s", filename); error(0,err_line,err_msg); continue; } if (!(bank[id].back_up= (unsigned char *) malloc(1<= '0' && tok1[i] <= '9') continue; else if (tok1[i] >= 'a' && tok1[i] <= 'f') continue; else if (tok1[i] >= 'A' && tok1[i] <= 'F') continue; else break; if (i != 2 && i != 4) { sprintf(err_line,ERROR_MAP,k); error(0,err_line," invalid offset or bank_id"); continue; } if (i == 2 && bank[i].type != '-') { sprintf(err_line,ERROR_MAP,k); error(0,err_line," offset is no virtuel bank_id"); continue; } sscanf(tok1,"%x",&offset); if (no_maps && offset < pre_off) { sprintf(err_line,ERROR_MAP,k); error(0,err_line," offset/bank_id not ascending sorted"); continue; } if (i==4 && (offset & (1<= 256 || p && *p || tok2[0]=='-' || tok2[0]=='+') { sprintf(err_line,ERROR_MAP,k); error(0,err_line," invalid port_id"); continue; } } if (no_maps && offset == pre_off && portno < pre_port) { sprintf(err_line,ERROR_MAP,k); error(0,err_line," offset/port_no not ascending sorted"); continue; } for (j=0;j<2;j++) if (tok3[j] >= '0' && tok3[j] <= '9') continue; else if (tok3[j] >= 'a' && tok3[j] <= 'f') continue; else if (tok3[j] >= 'A' && tok3[j] <= 'F') continue; else break; if (j != 2) { sprintf(err_line,ERROR_MAP,k); error(0,err_line," invalid mask"); continue; } sscanf(tok3,"%x",&mask); for (j=0;tok4[j];j++) if (j%3 == 2 && tok4[j]!=',') break; if (tok4[j] || j%3 != 2) { sprintf(err_line,ERROR_MAP,k); error(0,err_line," invalid format of bank_ids"); continue; } h= (j+1)/3; pre_id= 0; for (j=0;j= 256 || (p && *p && *p != ',') || tok4[3*j]=='-' || tok4[3*j]=='+') { char err_msg[32]; sprintf(err_line,ERROR_MAP,k); sprintf(err_msg," invalid %u-th bank_id: %3s",j+1,tok4+3*j); error(0,err_line,err_msg); break; } if (j && id <= pre_id) { sprintf(err_line,ERROR_MAP,k); error(0,err_line," bank_ids not ascending ordered"); break; } if (!bank[id].type) { char err_msg[32]; sprintf(err_line,ERROR_MAP,k); sprintf(err_msg," bank_id %u not defined",id); error(0,err_line,err_msg); break; } pre_id=id; } if (j < h) continue; if (!(mmm= (struct port_map *)realloc(map,(no_maps+1)*sizeof(struct port_map)))) { sprintf(err_line,ERROR_MAP,k); error(0,err_line," insufficent memory"); continue; } map=mmm; map[no_maps].virtuel= (i==2); map[no_maps].offset= offset; pre_off=offset; map[no_maps].port_no = portno; pre_port=portno; map[no_maps].mask = mask; map[no_maps].count = h; if (!(map[no_maps].bankids= (unsigned char*)malloc(h*sizeof(_uchar)))) { sprintf(err_line,ERROR_MAP,k); error(0,err_line," insufficent memory"); continue; } for (j=0;j>(2*(index>>delta))&1) ? empty : *(address_map[index>>delta]+index) ; } _uchar read_memo(unsigned short index) { if (cpu_pin[busrq]) acknowledge_bus_request(); if(!cpu_is_in_disassemble) ADDRESS=index; set_cpu_pin(rd,1); set_cpu_pin(mreq,1); if(!cpu_is_in_disassemble) wait_tics(TICS_MEMO); DATA= (!no_maps ? memory[index] : !all_readable && (access_type>>(2*(index>>delta))&1) ? empty : *(address_map[index>>delta]+index)) ; set_cpu_pin(mreq,0); set_cpu_pin(rd,0); return DATA; } _uchar read_opcode(unsigned short index, bool set_m1) { if (cpu_pin[busrq]) acknowledge_bus_request(); if (set_m1) set_cpu_pin(m1,1); if(!cpu_is_in_disassemble) ADDRESS=index; set_cpu_pin(rd,1); if (io_address) { DATA= *(io_address+index); if(!cpu_is_in_disassemble) wait_tics(TICS_MEMO); } else { set_cpu_pin(mreq,1); DATA= (!no_maps ? memory[index] : !all_readable && (access_type>>(2*(index>>delta))&1) ? empty : *(address_map[index>>delta]+index)) ; if(!cpu_is_in_disassemble) wait_tics(TICS_MEMO); set_cpu_pin(mreq,0); } set_cpu_pin(rd,0); if (set_m1) set_cpu_pin(m1,0); return DATA; } void write_memo(unsigned short index, unsigned char data) { if (cpu_pin[busrq]) acknowledge_bus_request(); if(!cpu_is_in_disassemble) ADDRESS=index; DATA=data; set_cpu_pin(wr,1); set_cpu_pin(mreq,1); if(!cpu_is_in_disassemble) wait_tics(TICS_MEMO); if (!no_maps) memory[index]=DATA; else if (!(access_type>>(2*(index>>delta))&2)) *(address_map[index>>delta]+index)=DATA; set_cpu_pin(mreq,0); set_cpu_pin(wr,0); } _uchar write_to_memory(_ushort index, _uchar data) { _uchar previous; set_cpu_pin(wr,1); if (io_address) { previous= *(io_address+index); *(io_address+index) = data; } else { set_cpu_pin(mreq,1); previous= (!no_maps ? memory[index] : !all_readable && (access_type>>(2*(index>>delta))&1) ? empty : *(address_map[index>>delta]+index)) ; if (!no_maps) memory[index]= data; else if (!(access_type>>(2*(index>>delta))&2)) *(address_map[index>>delta]+index)= data; set_cpu_pin(mreq,0); } set_cpu_pin(wr,0); return previous; } void clear_memory(void) { int i; if (!no_maps) memset(memory,empty,65536); else for (i=0;i<16;i++) if (!(access_type>>(2*i)&2)) memset(memory+(i<