umac/include/machw.h
Jeff Epler 0be2290d4a audio: Make the last byte of the audio buffer a trap address
at that point, there should be 370 contiguous, sensible samples
available, so let the front end grab them.

Sadly this adds a test to the "store byte in RAM" fast path, but it seems
to be unavoidable.

In the unix frontend, vsync is now presented based on the SDL audio
callback when enabled, instead of gettimeofday.
2025-03-19 13:31:38 -05:00

135 lines
5.7 KiB
C

/*
* Copyright 2024 Matt Evans
*
* Portions of the {READ,WRITE}_{BYTE,WORD,LONG} macros are from
* Musashi, Copyright 1998-2002 Karl Stenerud.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef MACHW_H
#define MACHW_H
#include "rom.h"
#define ROM_ADDR 0x400000 /* Regular base (and 0, when overlay=0 */
#define RAM_SIZE (1024*UMAC_MEMSIZE)
#define RAM_HIGH_ADDR 0x600000
#define PV_SONY_ADDR 0xc00069 /* Magic address for replacement driver PV ops */
////////////////////////////////////////////////////////////////////////////////
// RAM accessors
//
// This isn't a wonderful place, but RAM access is needed in various files.
extern uint8_t *_ram_base;
extern uint8_t *_rom_base;
static inline uint8_t *ram_get_base(void)
{
return _ram_base;
}
static inline uint8_t *rom_get_base(void)
{
return _rom_base;
}
extern int overlay;
#define ADR24(x) ((x) & 0xffffff)
/* Let's do it like this:
*
* When overlay=1: (reset)
* - ROM is at 0-0x10_0000 (hm, to 0x40_0000 pretty much) and 0x40_0000-0x50_0000
* - RAM is at 0x60_0000-0x80_0000
*
* When overlay=0:
* - ROM is at 0x40_0000-0x50_0000
* - RAM is at 0-0x40_0000
* - manuals say 0x60_0000-0x80_00000 is "unassigned", but may as well make RAM here too
*
* i.e. RAM is 60-80, or !overlay and 0. And ROM is 40-50, or overlay and 0.
*/
#define IS_ROM(x) (((ADR24(x) & 0xf00000) == ROM_ADDR) || (overlay && (ADR24(x) & 0xf00000) == 0))
/* RAM: always at 0x600000-0x7fffff, sometimes at 0 (0 most likely so check first!) */
#define IS_RAM(x) ((!overlay && ((ADR24(x) & 0xc00000) == 0)) || ((ADR24(x) & 0xe00000) == RAM_HIGH_ADDR))
/* For regular power-of-two memory sizes, this should resolve to a
* simple mask (i.e. be fast). For non-Po2 (e.g. a Mac208K), this
* involves a divide when an access is made off the end of memory.
* But, that should never happen post-boot.
*/
#define CLAMP_RAM_ADDR(x) ((x) >= RAM_SIZE ? (x) % RAM_SIZE : (x))
/* Is the address (previously clamped with CLAMP_RAM_ADDR) the audio trap address? (last byte of audio data) */
#define IS_RAM_AUDIO_TRAP(x) (x == umac_get_audio_offset() + 2 * 369)
#define IS_VIA(x) ((ADR24(x) & 0xe80000) == 0xe80000)
#define IS_IWM(x) ((ADR24(x) >= 0xdfe1ff) && (ADR24(x) < (0xdfe1ff + 0x2000)))
#define IS_SCC_RD(x) ((ADR24(x) & 0xf00000) == 0x900000)
#define IS_SCC_WR(x) ((ADR24(x) & 0xf00000) == 0xb00000)
#define IS_DUMMY(x) (((ADR24(x) >= 0x800000) && (ADR24(x) < 0x9ffff8)) || ((ADR24(x) & 0xf00000) == 0x500000))
#define IS_TESTSW(x) (ADR24(x) >= 0xf00000)
/* Unaligned/BE read/write macros from Mushashi: */
#define READ_BYTE(BASE, ADDR) (BASE)[ADDR]
#define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) | \
(BASE)[(ADDR)+1])
#define READ_LONG(BASE, ADDR) (((BASE)[ADDR]<<24) | \
((BASE)[(ADDR)+1]<<16) | \
((BASE)[(ADDR)+2]<<8) | \
(BASE)[(ADDR)+3])
#define READ_WORD_AL(BASE, ADDR) (__builtin_bswap16(*(uint16_t *)&(BASE)[(ADDR)]))
#define WRITE_BYTE(BASE, ADDR, VAL) do { \
(BASE)[ADDR] = (VAL)&0xff; \
} while(0)
#define WRITE_WORD(BASE, ADDR, VAL) do { \
(BASE)[ADDR] = ((VAL)>>8) & 0xff; \
(BASE)[(ADDR)+1] = (VAL)&0xff; \
} while(0)
#define WRITE_LONG(BASE, ADDR, VAL) do { \
(BASE)[ADDR] = ((VAL)>>24) & 0xff; \
(BASE)[(ADDR)+1] = ((VAL)>>16)&0xff; \
(BASE)[(ADDR)+2] = ((VAL)>>8)&0xff; \
(BASE)[(ADDR)+3] = (VAL)&0xff; \
} while(0)
/* Specific RAM/ROM access: */
#define RAM_RD8(addr) READ_BYTE(_ram_base, addr)
#define RAM_RD16(addr) READ_WORD(_ram_base, addr)
#define RAM_RD_ALIGNED_BE16(addr) READ_WORD_AL(_ram_base, addr)
#define RAM_RD32(addr) READ_LONG(_ram_base, addr)
#define RAM_WR8(addr, val) WRITE_BYTE(_ram_base, addr, val)
#define RAM_WR16(addr, val) WRITE_WORD(_ram_base, addr, val)
#define RAM_WR32(addr, val) WRITE_LONG(_ram_base, addr, val)
#define ROM_RD8(addr) READ_BYTE(_rom_base, addr)
#define ROM_RD16(addr) READ_WORD(_rom_base, addr)
#define ROM_RD_ALIGNED_BE16(addr) READ_WORD_AL(_rom_base, addr)
#define ROM_RD32(addr) READ_LONG(_rom_base, addr)
#endif