ultimecia

A ps1 emulator in c
Log | Files | Refs

mem.c (4335B)


      1 #include <stdlib.h>
      2 #include <string.h>
      3 #include <stdio.h>
      4 #include "mem.h"
      5 #include "types.h"
      6 #include "util.h"
      7 #include "log.h"
      8 
      9 Channel*
     10 CHANNEL_new(void)
     11 {
     12   Channel* ch = (Channel*)malloc(sizeof(Channel));
     13   ch->enable = 0;
     14   ch->direction = DIR_TO_RAM;
     15   ch->step = STEP_INCREMENT;
     16   ch->sync = SYNC_MANUAL;
     17   ch->base = 0;
     18   ch->trigger = 0;
     19   ch->chop = 0;
     20   ch->chop_dma_sz = 0;
     21   ch->chop_cpu_sz = 0;
     22   ch->dummy = 0;
     23   ch->block_size = 0;
     24   ch->block_count = 0;
     25   return ch;
     26 }
     27 
     28 u32
     29 CHANNEL_control(Channel* ch)
     30 {
     31   u32 r;
     32   r = 0;
     33 
     34   r |= ((u32)ch->direction) << 0;
     35   r |= ((u32)ch->step) << 1;
     36   r |= ((u32)ch->chop) << 8;
     37   r |= ((u32)ch->sync) << 9;
     38   r |= ((u32)ch->chop_dma_sz) << 16;
     39   r |= ((u32)ch->chop_cpu_sz) << 20;
     40   r |= ((u32)ch->enable) << 24;
     41   r |= ((u32)ch->trigger) << 28;
     42   r |= ((u32)ch->dummy) << 29;
     43 
     44   return r;
     45 }
     46 
     47 void
     48 CHANNEL_set_control(Channel* ch, u32 val)
     49 {
     50   ch->direction = (Direction)(val & 1);
     51   ch->step = (Step)((val >> 1) & 1); 
     52   ch->chop = (val >> 8) & 1;
     53   ch->sync = (Sync)((val >> 9) & 3);
     54   ch->chop_dma_sz = (u8)((val >> 16) & 7);
     55   ch->chop_cpu_sz = (u8)((val >> 20) & 7);
     56   ch->enable = ((val >> 24) & 1);
     57   ch->trigger = ((val >> 28) & 1);
     58   ch->dummy = (u8)((val >> 29) & 3);
     59 }
     60 
     61 u32
     62 CHANNEL_base(Channel* ch)
     63 {
     64   return ch->base;
     65 }
     66 
     67 void
     68 CHANNEL_set_base(Channel* ch, u32 val)
     69 {
     70   ch->base = val & 0xffffff;
     71 }
     72 
     73 u32
     74 CHANNEL_block_control(Channel* ch)
     75 {
     76   u32 bs, bc;
     77 
     78   bs = (u32)ch->block_size;
     79   bc = (u32)ch->block_count;
     80 
     81   return (bc << 16) | bs;
     82 }
     83 
     84 void
     85 CHANNEL_set_block_control(Channel* ch, u32 val)
     86 {
     87   ch->block_size = (u16)val;
     88   ch->block_count = (u16)(val >> 16);
     89 }
     90 
     91 u8
     92 CHANNEL_active(Channel* ch)
     93 {
     94   u8 trigger;
     95   switch (ch->sync)
     96   {
     97   case SYNC_MANUAL: trigger = ch->trigger; break;
     98   default: trigger = 1; break;
     99   }
    100   return ch->enable && trigger;
    101 
    102 }
    103 
    104 u8
    105 CHANNEL_transfer_size(Channel* ch, u32 *res)
    106 {
    107 	switch (ch->sync) {
    108 	case SYNC_MANUAL: 
    109 		*res = (u32)ch->block_size;
    110 		return 1;
    111 	case SYNC_REQUEST:
    112 		*res = (u32)((u32)ch->block_size * (u32)(ch->block_count));
    113 		return 1;
    114 	case SYNC_LINKED_LIST: return 0;
    115 	default: log_fatal("UNREACHABLE"); exit(EXIT_FAILURE);
    116 	}
    117 }
    118 
    119 void
    120 CHANNEL_done(Channel* ch)
    121 {
    122 	ch->enable = 0;
    123 	ch->trigger = 0;
    124 }
    125 
    126 DMA*
    127 DMA_new(void)
    128 {
    129   DMA* dma = (DMA*)malloc(sizeof(DMA));
    130   dma->control = 0x07654321;
    131   dma->irq_en = 0;
    132   dma->channel_irq_en = 0;
    133   dma->channel_irq_flags = 0;
    134   dma->force_irq = 0;
    135   dma->irq_dummy = 0;
    136   memset(dma->channels, 0, sizeof(Channel)*7);
    137   return dma;
    138 }
    139 
    140 u32
    141 DMA_control(DMA* dma)
    142 {
    143   return dma->control;
    144 }
    145 
    146 void
    147 DMA_set_control(DMA* dma, u32 val)
    148 {
    149   dma->control = val;
    150 }
    151 
    152 u8
    153 DMA_irq(DMA* dma)
    154 {
    155   u32 channel_irq;
    156   channel_irq = dma->channel_irq_flags & dma->channel_irq_en;
    157   return (dma->force_irq || (dma->irq_en && channel_irq != 0));
    158 }
    159 
    160 u32
    161 DMA_interrupt(DMA* dma)
    162 {
    163   u32 r;
    164   r = 0;
    165 
    166   r |= (u32)dma->irq_dummy;
    167   r |= ((u32)dma->force_irq) << 15;
    168   r |= ((u32)dma->channel_irq_en) << 16;
    169   r |= ((u32)dma->irq_en) << 23;
    170   r |= ((u32)dma->channel_irq_flags) << 24;
    171   r |= ((u32)DMA_irq(dma)) << 31;
    172 
    173   return r;
    174 }
    175 
    176 void
    177 DMA_set_interrupt(DMA* dma, u32 val)
    178 {
    179   u32 ack;
    180 
    181   dma->irq_dummy = (u8)(val & 0x3f);
    182   dma->force_irq = (val >> 15) & 1;
    183   dma->channel_irq_en = (u8)((val >> 16) & 0x7f);
    184   dma->irq_en = (val >> 23) & 1;
    185 
    186   ack = (u8)((val >> 24) & 0x3f);
    187   dma->channel_irq_flags &= ~ack;
    188 }
    189 
    190 RAM*
    191 RAM_new(void) 
    192 {
    193   RAM* ram = (RAM*)(malloc(sizeof(RAM)));
    194   ram->data = (u8*)(malloc(sizeof(u8) * RAM_SIZE));
    195 
    196   memset(ram->data, 0xca, RAM_SIZE);
    197   return ram;
    198 }
    199 
    200 u32
    201 RAM_load32(RAM* r, u32 offset)
    202 {
    203   return (r->data[offset + 3] << 24) | 
    204     (r->data[offset + 2] << 16) | 
    205     (r->data[offset + 1] <<  8) | 
    206     (r->data[offset + 0]);
    207 }
    208 
    209 u16
    210 RAM_load16(RAM* r, u32 offset)
    211 {
    212   u16 b0, b1;
    213 
    214   b0 = (u16)r->data[offset];
    215   b1 = (u16)r->data[offset + 1];
    216 
    217   return b0 | (b1 << 8);
    218 }
    219 
    220 u8
    221 RAM_load8(RAM* r, u32 offset)
    222 {
    223   return r->data[offset];
    224 }
    225 
    226 void
    227 RAM_store8(RAM* r, u32 offset, u8 val)
    228 {
    229   r->data[offset]=val;
    230 }
    231 
    232 void
    233 RAM_store16(RAM* r, u32 offset, u16 val)
    234 {
    235   r->data[offset]=val;
    236   r->data[offset+1] = val >> 8;
    237 }
    238 
    239 void
    240 RAM_store32(RAM* r, u32 offset, u32 val)
    241 {
    242   u8 b0 = val;
    243   u8 b1 = (val >> 8); 
    244   u8 b2 = (val >> 16);
    245   u8 b3 = (val >> 24);
    246 
    247   r->data[offset + 0] = b0;
    248   r->data[offset + 1] = b1;
    249   r->data[offset + 2] = b2;
    250   r->data[offset + 3] = b3;
    251 }