2019-07-02 02:15:33 +00:00
|
|
|
//DingusPPC - Prototype 5bf2
|
|
|
|
//Written by divingkatae
|
|
|
|
//(c)2018-20 (theweirdo)
|
|
|
|
//Please ask for permission
|
|
|
|
//if you want to distribute this.
|
|
|
|
//(divingkatae#1017 on Discord)
|
|
|
|
|
|
|
|
//Functionality for the MPC106
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cinttypes>
|
2019-08-18 23:34:24 +00:00
|
|
|
#include "../viacuda.h"
|
2019-07-02 02:15:33 +00:00
|
|
|
#include "mpc106.h"
|
2019-08-18 23:34:24 +00:00
|
|
|
#include "../ppcemumain.h"
|
|
|
|
#include "../ppcmemory.h"
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2019-07-15 00:05:10 +00:00
|
|
|
bool mpc106_membound_change;
|
|
|
|
bool mpc106_mem_approve; //Confirm memory transaction
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2019-07-07 06:10:32 +00:00
|
|
|
uint32_t mpc106_address; // For fe000000 - fe00ffff
|
|
|
|
uint32_t mpc_config_addr; // Device No. and Reg No. included
|
|
|
|
uint32_t mpc_config_dat; // Value to write to the device
|
2019-07-15 00:05:10 +00:00
|
|
|
uint32_t cust_grab_size; // Custom bit size
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
uint32_t mpc106_write_word;
|
|
|
|
uint32_t mpc106_read_word;
|
|
|
|
uint16_t mpc106_write_half;
|
|
|
|
uint16_t mpc106_read_half;
|
|
|
|
uint8_t mpc106_write_byte;
|
|
|
|
uint8_t mpc106_read_byte;
|
|
|
|
|
2019-07-15 00:05:10 +00:00
|
|
|
uint8_t mpc106_word_custom_size;
|
|
|
|
|
|
|
|
//The below array is used for ROM banks
|
|
|
|
//Top eight entries are for the starting addresses
|
|
|
|
//Bottom eight entries are for the ending addresses
|
|
|
|
uint32_t mpc106_memory_bounds[16] =
|
|
|
|
{
|
|
|
|
0x00000, 0x00000, 0x00000, 0x00000,
|
|
|
|
0x00000, 0x00000, 0x00000, 0x00000,
|
|
|
|
0xFFFFF, 0xFFFFF, 0xFFFFF, 0xFFFFF,
|
|
|
|
0xFFFFF, 0xFFFFF, 0xFFFFF, 0xFFFFF,
|
|
|
|
};
|
|
|
|
|
|
|
|
//Entries are organized like so...
|
|
|
|
|
|
|
|
//ROM Banks 0-3 (ext. starting address) (starting address) (0x00000)
|
|
|
|
//ROM Banks 4-7 (ext. starting address) (starting address) (0x00000)
|
|
|
|
//ROM Banks 0-3 (ext. ending address) ( ending address) (0x00000)
|
|
|
|
//ROM Banks 4-7 (ext. ending address) ( ending address) (0x00000)
|
|
|
|
|
2019-07-02 02:15:33 +00:00
|
|
|
void mpc106_init(){
|
2019-07-07 06:10:32 +00:00
|
|
|
mpc_config_addr = 0;
|
|
|
|
mpc_config_dat = 0;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
//Initialize Vendor & Device IDs
|
2019-07-12 05:27:14 +00:00
|
|
|
machine_fexxxx_mem[0x00] = 0x57;
|
|
|
|
machine_fexxxx_mem[0x01] = 0x10;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2019-07-12 05:27:14 +00:00
|
|
|
machine_fexxxx_mem[0x02] = 0x02;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
//PCI command + status
|
2019-07-12 05:27:14 +00:00
|
|
|
machine_fexxxx_mem[0x04] = 0x06;
|
|
|
|
machine_fexxxx_mem[0x06] = 0x80;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2019-07-12 05:27:14 +00:00
|
|
|
machine_fexxxx_mem[0x0B] = 0x06;
|
|
|
|
machine_fexxxx_mem[0x0C] = 0x08;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2019-07-12 05:27:14 +00:00
|
|
|
machine_fexxxx_mem[0x73] = 0xCD;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2019-07-12 05:27:14 +00:00
|
|
|
machine_fexxxx_mem[0xA8] = 0x10;
|
|
|
|
machine_fexxxx_mem[0xA9] = 0x00;
|
|
|
|
machine_fexxxx_mem[0xAA] = 0x00;
|
|
|
|
machine_fexxxx_mem[0xAB] = 0xFF;
|
|
|
|
|
|
|
|
machine_fexxxx_mem[0xAC] = 0x0C;
|
|
|
|
machine_fexxxx_mem[0xAD] = 0x06;
|
|
|
|
machine_fexxxx_mem[0xAE] = 0x0C;
|
|
|
|
machine_fexxxx_mem[0xAF] = 0x00;
|
|
|
|
|
|
|
|
machine_fexxxx_mem[0xBA] = 0x04;
|
2019-07-15 00:05:10 +00:00
|
|
|
machine_fexxxx_mem[0xC0] = 0x01;
|
2019-07-12 05:27:14 +00:00
|
|
|
|
2019-07-15 00:05:10 +00:00
|
|
|
machine_fexxxx_mem[0xE0] = 0x42;
|
|
|
|
machine_fexxxx_mem[0xE1] = 0x00;
|
|
|
|
machine_fexxxx_mem[0xE2] = 0xFF;
|
|
|
|
machine_fexxxx_mem[0xE3] = 0x0F;
|
2019-07-12 05:27:14 +00:00
|
|
|
|
|
|
|
machine_fexxxx_mem[0xF0] = 0x00;
|
|
|
|
machine_fexxxx_mem[0xF1] = 0x00;
|
|
|
|
machine_fexxxx_mem[0xF2] = 0x02;
|
|
|
|
machine_fexxxx_mem[0xF3] = 0xFF;
|
|
|
|
|
|
|
|
machine_fexxxx_mem[0xF4] = 0x03;
|
|
|
|
machine_fexxxx_mem[0xF5] = 0x00;
|
|
|
|
machine_fexxxx_mem[0xF6] = 0x00;
|
|
|
|
machine_fexxxx_mem[0xF7] = 0x00;
|
|
|
|
|
|
|
|
machine_fexxxx_mem[0xFC] = 0x00;
|
|
|
|
machine_fexxxx_mem[0xFD] = 0x00;
|
|
|
|
machine_fexxxx_mem[0xFE] = 0x10;
|
|
|
|
machine_fexxxx_mem[0xFF] = 0x00;
|
2019-07-15 00:05:10 +00:00
|
|
|
|
|
|
|
mpc106_mem_approve = false;
|
|
|
|
mpc106_word_custom_size = 0;
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2019-07-07 06:10:32 +00:00
|
|
|
uint32_t mpc106_write_device(uint32_t device_addr, uint32_t insert_to_device, uint8_t bit_length){
|
|
|
|
//Write to the specified device - Invoked when a write is made to 0xFEExxxxx.
|
2019-07-12 05:27:14 +00:00
|
|
|
//device_addr is what's stored in 0xFEC00CF8 (The MPG106/Grackle's CONFIG_ADDR Register).
|
2019-07-07 06:10:32 +00:00
|
|
|
|
|
|
|
uint32_t reg_num = (device_addr & 0x07FC) >> 2;
|
|
|
|
uint32_t dev_num = (device_addr & 0xF800) >> 11;
|
2019-07-12 05:27:14 +00:00
|
|
|
|
|
|
|
switch(dev_num){
|
|
|
|
case 0:
|
|
|
|
//Device 0 is reserved to the grackle by default
|
|
|
|
mpc106_address = reg_num;
|
|
|
|
mpc106_write(insert_to_device);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
case 17:
|
|
|
|
via_cuda_address = (reg_num << 9) + (dev_num << 12) + 0x3000000;
|
|
|
|
via_write_byte = (uint8_t)insert_to_device;
|
|
|
|
via_cuda_write();
|
|
|
|
break;
|
2019-07-07 06:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2019-07-07 06:10:32 +00:00
|
|
|
uint32_t mpc106_read_device(uint32_t device_addr, uint8_t bit_length){
|
|
|
|
//Read to the specified device - Invoked when a read is made to 0xFEExxxxx.
|
2019-07-12 05:27:14 +00:00
|
|
|
//device_addr is what's stored in 0xFEC00CF8 (The MPG106/Grackle's CONFIG_ADDR Register).
|
2019-07-07 06:10:32 +00:00
|
|
|
|
|
|
|
uint32_t reg_num = (device_addr & 0x07FC) >> 2;
|
|
|
|
uint32_t dev_num = (device_addr & 0xF800) >> 11;
|
|
|
|
|
|
|
|
uint32_t grab_value = 0;
|
|
|
|
|
2019-07-12 05:27:14 +00:00
|
|
|
switch(dev_num){
|
|
|
|
case 0:
|
|
|
|
//Device 0 is reserved to the grackle by default
|
|
|
|
mpc106_address = reg_num;
|
|
|
|
mpc106_read();
|
|
|
|
grab_value = mpc106_read_word;
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
case 17:
|
|
|
|
via_cuda_address = (reg_num << 8) + (dev_num << 12) + 0x3000000;
|
|
|
|
via_cuda_read();
|
|
|
|
grab_value = (uint32_t)via_read_byte;
|
|
|
|
break;
|
2019-07-07 06:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return grab_value;
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2019-07-15 00:05:10 +00:00
|
|
|
bool mpc106_check_membound(uint32_t attempted_address){
|
|
|
|
uint32_t mem_address_begin;
|
|
|
|
uint32_t mem_address_end;
|
|
|
|
for (int get_rom_bank = 0; get_rom_bank < 8; get_rom_bank++){
|
|
|
|
mem_address_begin = mpc106_memory_bounds[get_rom_bank];
|
|
|
|
mem_address_end = mpc106_memory_bounds[get_rom_bank + 8];
|
|
|
|
if ((attempted_address >= mem_address_begin) & (attempted_address <= mem_address_end)){
|
|
|
|
uint8_t is_valid = (machine_fexxxx_mem[0xA0] >> get_rom_bank) & 0x01;
|
|
|
|
if (is_valid == 0){
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void mpc106_set_membound_begin(uint8_t bound_area){
|
|
|
|
uint32_t bcheck_area = 0x80 + bound_area;
|
|
|
|
uint32_t newbound = machine_fexxxx_mem[bcheck_area];
|
|
|
|
uint32_t bound_entry = bound_area % 8;
|
|
|
|
uint32_t change_entry = mpc106_memory_bounds[bound_entry];
|
|
|
|
change_entry &= 0xfffff;
|
|
|
|
change_entry = newbound << 20;
|
|
|
|
mpc106_memory_bounds[bound_entry] = change_entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mpc106_set_membound_extbegin(uint8_t bound_area){
|
|
|
|
uint32_t bcheck_area = 0x88 + bound_area;
|
|
|
|
uint32_t newbound = machine_fexxxx_mem[bcheck_area];
|
|
|
|
uint32_t bound_entry = bound_area % 8;
|
|
|
|
uint32_t change_entry = mpc106_memory_bounds[bound_entry];
|
|
|
|
change_entry &= 0x0fffffff;
|
|
|
|
change_entry = (newbound & 0x3) << 28;
|
|
|
|
mpc106_memory_bounds[bound_entry] = change_entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mpc106_set_membound_end(uint8_t bound_area){
|
|
|
|
uint32_t bcheck_area = 0x90 + bound_area;
|
|
|
|
uint32_t newbound = machine_fexxxx_mem[bcheck_area];
|
|
|
|
uint32_t bound_entry = (bound_area % 8) + 8;
|
|
|
|
uint32_t change_entry = mpc106_memory_bounds[bound_entry];
|
|
|
|
change_entry &= 0xfffff;
|
|
|
|
change_entry = newbound << 20;
|
|
|
|
mpc106_memory_bounds[bound_entry] = change_entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mpc106_set_membound_extend(uint8_t bound_area){
|
|
|
|
uint32_t bcheck_area = 0x98 + bound_area;
|
|
|
|
uint32_t newbound = machine_fexxxx_mem[bcheck_area];
|
|
|
|
uint32_t bound_entry = (bound_area % 8) + 8;
|
|
|
|
uint32_t change_entry = mpc106_memory_bounds[bound_entry];
|
|
|
|
change_entry &= 0x0fffffff;
|
|
|
|
change_entry = (newbound & 0x3) << 28;
|
|
|
|
mpc106_memory_bounds[bound_entry] = change_entry;
|
|
|
|
}
|
|
|
|
|
2019-07-02 02:15:33 +00:00
|
|
|
void mpc106_read(){
|
|
|
|
|
|
|
|
uint8_t read_length = 4;
|
|
|
|
|
2019-07-15 00:05:10 +00:00
|
|
|
|
|
|
|
if ((mpc106_address >= 0x80) | (mpc106_address < 0xA0)){
|
|
|
|
mpc106_membound_change = true;
|
|
|
|
read_length = mpc106_word_custom_size;
|
|
|
|
}
|
|
|
|
else{
|
2019-07-02 02:15:33 +00:00
|
|
|
switch (mpc106_address){
|
|
|
|
case 0x8:
|
2019-07-12 05:27:14 +00:00
|
|
|
case 0x9:
|
|
|
|
case 0xA:
|
|
|
|
case 0xB:
|
|
|
|
case 0xC:
|
|
|
|
case 0xD:
|
|
|
|
case 0xE:
|
|
|
|
case 0xF:
|
|
|
|
case 0x3C:
|
|
|
|
case 0x3D:
|
|
|
|
case 0x3E:
|
|
|
|
case 0x3F:
|
2019-07-02 02:15:33 +00:00
|
|
|
case 0x72:
|
|
|
|
case 0x73:
|
|
|
|
case 0xA0:
|
|
|
|
case 0xA3:
|
|
|
|
read_length = 1;
|
|
|
|
break;
|
|
|
|
case 0x0:
|
|
|
|
case 0x2:
|
|
|
|
case 0x4:
|
|
|
|
case 0x6:
|
|
|
|
case 0x70:
|
|
|
|
read_length = 2;
|
|
|
|
break;
|
|
|
|
case 0xF0:
|
|
|
|
case 0xF4:
|
|
|
|
case 0xF8:
|
|
|
|
case 0xFC:
|
|
|
|
read_length = 4;
|
2019-07-12 05:27:14 +00:00
|
|
|
default: //Avoid writing into reserved areas
|
|
|
|
read_length = 0;
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
2019-07-15 00:05:10 +00:00
|
|
|
}
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
switch(read_length){
|
|
|
|
case 1:
|
|
|
|
mpc106_read_word |= (grab_macmem_ptr[mpc106_address]);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]);
|
|
|
|
mpc106_read_word |= (grab_macmem_ptr[mpc106_address]) << 8;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]);
|
|
|
|
mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]) << 8;
|
|
|
|
mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]) << 16;
|
|
|
|
mpc106_read_word |= (grab_macmem_ptr[mpc106_address]) << 24;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void mpc106_write(uint32_t write_word){
|
|
|
|
|
|
|
|
uint8_t write_length = 4;
|
|
|
|
|
2019-07-15 00:05:10 +00:00
|
|
|
if ((mpc106_address >= 0x80) | (mpc106_address < 0xA0)){
|
|
|
|
mpc106_membound_change = true;
|
|
|
|
write_length = mpc106_word_custom_size;
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
2019-07-15 00:05:10 +00:00
|
|
|
else{
|
|
|
|
switch (mpc106_address){
|
|
|
|
case 0x70:
|
|
|
|
case 0x72:
|
|
|
|
case 0x73:
|
|
|
|
case 0xA0:
|
|
|
|
case 0xA3:
|
|
|
|
write_length = 1;
|
2019-07-02 02:15:33 +00:00
|
|
|
break;
|
2019-07-15 00:05:10 +00:00
|
|
|
case 0x4:
|
|
|
|
case 0x6:
|
|
|
|
write_length = 2;
|
2019-07-02 02:15:33 +00:00
|
|
|
break;
|
2019-07-15 00:05:10 +00:00
|
|
|
case 0xF0:
|
|
|
|
case 0xF4:
|
|
|
|
case 0xF8:
|
|
|
|
case 0xFC:
|
|
|
|
write_length = 4;
|
|
|
|
default: //Avoid writing into reserved areas
|
|
|
|
write_length = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mpc106_membound_change){
|
|
|
|
switch(write_length){
|
|
|
|
case 1:
|
|
|
|
change_membound_time();
|
|
|
|
grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word) & 0xFF);
|
2019-07-12 05:27:14 +00:00
|
|
|
break;
|
2019-07-15 00:05:10 +00:00
|
|
|
case 2:
|
|
|
|
change_membound_time();
|
|
|
|
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF);
|
|
|
|
change_membound_time();
|
|
|
|
grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
change_membound_time();
|
|
|
|
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF);
|
|
|
|
change_membound_time();
|
|
|
|
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF);
|
|
|
|
change_membound_time();
|
|
|
|
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 16) & 0xFF);
|
|
|
|
change_membound_time();
|
|
|
|
grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 24) & 0xFF);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
switch(write_length){
|
|
|
|
case 1:
|
|
|
|
grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word) & 0xFF);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF);
|
|
|
|
grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF);
|
|
|
|
break;
|
|
|
|
case 4:
|
2019-07-12 05:27:14 +00:00
|
|
|
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF);
|
|
|
|
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF);
|
|
|
|
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 16) & 0xFF);
|
|
|
|
grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 24) & 0xFF);
|
|
|
|
break;
|
|
|
|
}
|
2019-07-15 00:05:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void change_membound_time(){
|
|
|
|
if (mpc106_address < 0x88){
|
|
|
|
mpc106_set_membound_begin(mpc106_address);
|
|
|
|
mpc106_membound_change = false;
|
|
|
|
}
|
|
|
|
else if (mpc106_address < 0x90){
|
|
|
|
mpc106_set_membound_extbegin(mpc106_address);
|
|
|
|
mpc106_membound_change = false;
|
|
|
|
}
|
|
|
|
else if (mpc106_address < 0x98){
|
|
|
|
mpc106_set_membound_end(mpc106_address);
|
|
|
|
mpc106_membound_change = false;
|
|
|
|
}
|
|
|
|
else if (mpc106_address < 0xA0){
|
|
|
|
mpc106_set_membound_extend(mpc106_address);
|
|
|
|
mpc106_membound_change = false;
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
}
|