summaryrefslogtreecommitdiff
path: root/emu/bus.c
blob: 33617c7b82da3bdefa3290d09edb11a35456b030 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "bus.h"

#include <stdio.h>
#include <stdlib.h>

static device_vtable_t const bus_vtable = {
	bus_read,
	bus_write,
#ifdef WITH_GUI
	bus_draw,
#endif
	bus_deinit
};

void bus_init( bus_t *bus )
{
	device_init( &bus->base, "bus" );
	((device_t *)bus)->vtable = (device_vtable_t *)&bus_vtable;
	
	bus->nof_devices = 0;	
}

void bus_register( bus_t *bus, device_t *device, uint16_t from, uint16_t to )
{
	if( bus->nof_devices < MAX_NOF_DEVICES ) {
		registered_device_t *reg = &bus->devices[bus->nof_devices];
		reg->device = device;
		reg->from = from;
		reg->to = to;
		bus->nof_devices++;
	} else {
		fprintf( stderr, "ERROR: too many devices on bus\n" );
		exit( EXIT_FAILURE );
	}
}

uint8_t bus_read( void *obj, uint16_t addr )
{
	bus_t *bus = (bus_t *)obj;

	for( int i = 0; i < bus->nof_devices; i++ ) {
		registered_device_t *reg = &bus->devices[i];
		if( reg->from <= addr && addr <= reg->to ) {
			return reg->device->vtable->read( reg->device, addr );
		}
	}

	fprintf( stderr, "ERROR: illegal bus access reading from address %04X\n", addr );
	
	return 0;
}

void bus_write( void *obj, uint16_t addr, uint8_t data )
{
	bus_t *bus = (bus_t *)obj;

	for( int i = 0; i < bus->nof_devices; i++ ) {
		registered_device_t *reg = &bus->devices[i];
		if( reg->from <= addr && addr <= reg->to ) {
			reg->device->vtable->write( reg->device, addr, data );
			return;
		}
	}

	fprintf( stderr, "ERROR: illegal bus access writing to address %04X\n", addr );
}

#ifdef WITH_GUI
void bus_draw( void *obj, SDL_Renderer *renderer )
{
	bus_t *bus = (bus_t *)obj;

	for( int i = 0; i < bus->nof_devices; i++ ) {
		device_t *device = bus->devices[i].device;
		device->vtable->draw( device, renderer );
	}
}
#endif

void bus_deinit( void *obj )
{
	bus_t *bus = (bus_t *)obj;

	for( int i = bus->nof_devices - 1; i >= 0; i-- ) {
		registered_device_t *reg = &bus->devices[i];
		reg->device->vtable->deinit( reg->device );
	}
	bus->nof_devices = 0;

	device_deinit( &bus->base );
}