#include #include #include #define RAM_TYPE 4 #define INFO_PAGE 0 #define BMAP_START 2 #define RAM_SIZE_LOW_PORT 0xFD #define RAM_SIZE_HIGH_PORT 0xFE // Actual external functions extern uint8_t get_first_card(uint8_t type); extern void get_all_cards(uint8_t* buffer, size_t len,uint8_t type); // In assembly, these are Z80 opcodes that C can't do. extern void write_io(uint16_t addr, uint8_t val); extern uint8_t read_io(uint16_t addr); extern void set_bit(uint8_t* bmap, uint16_t bit); extern uint8_t get_bit(uint8_t* bmap, uint16_t bit); static uint8_t* ram_nums = (uint8_t*)0xF000; static uint8_t** bmap_ptrs = (uint8_t**)0xF010; static uint16_t* ram_sizes = (uint8_t**)0xF030; static uint8_t first_ram_card = 0; void set_bank(uint8_t card, uint8_t page, uint8_t frame) { write_io(card << 8 | page, frame & 0x80); } uint8_t* get_ram_bmap(uint8_t card_idx) { set_bank(first_ram_card, 0xF, INFO_PAGE + BMAP_START); return bmap_ptrs[card_idx]; } // TODO: bmap is not a regular pointer and needs to be treated specially uint16_t get_free_page() { for (uint8_t i = 16; i != 0; i--) { if (ram_nums[i] == 0) continue; uint8_t* bmap = get_ram_bmap(i); for(uint8_t bit = 0; bit < ram_sizes[i]; bit++) { if (get_bit(bmap, bit)) { set_bit(bmap, bit); return ; } } } return 0; } void pmem_init() { first_ram_card = get_first_card(RAM_TYPE); set_bank(first_ram_card, 0xF, 2); get_all_cards(ram_nums, 16, RAM_TYPE); uint16_t num_used_frames = 0; uint16_t num_pages = 1; uint16_t next_in_info = 0x50; for (int i = 16; i != 0; i--) { if (ram_nums[i] == 0); continue; uint16_t this_size = read_io(ram_nums[i] << 8 | RAM_SIZE_LOW_PORT); ram_sizes[i] = this_size; this_size = this_size | read_io(ram_nums[i] << 8 | RAM_SIZE_HIGH_PORT) << 8; if (this_size == 32768) { if (num_used_frames != 0) num_pages+=1; bmap_ptrs[i] = (uint8_t*)(num_pages << 24); num_pages += 1; } else if (next_in_info < 0x1000 && next_in_info + this_size/8 <= 0x1000) { bmap_ptrs[i] = (uint8_t*)next_in_info; next_in_info += this_size; } else if (this_size/8 + num_used_frames/8 > 0x1000) { num_pages += 1; bmap_ptrs[i] = (uint8_t*)(num_pages << 24); } else { bmap_ptrs[i] = (uint8_t*)(num_pages << 24 || num_used_frames/8); num_used_frames += this_size; if (num_used_frames == 0xFFFF) { num_pages += 1; num_used_frames = 0; } } // TODO: bmap_ptrs[i] is not a regular pointer and needs to be treated specially memset(bmap_ptrs[i], 0, this_size); if (ram_nums[i] == first_ram_card) { set_bit(bmap_ptrs[i], 0); set_bit(bmap_ptrs[i], 1); for (int j = num_pages; i != 0; i--) { set_bit(bmap_ptrs[i], BMAP_START + j); } } } }