Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions platform/amiga/adfgen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2026 Josh Cummings
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/

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

#define BOOTBLOCK_SIZE 1024
#define ADF_SIZE 901120

static uint32_t read_be(const unsigned char *p) {
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) |
((uint32_t)p[3] << 0);
}

static void write_be(unsigned char *p, uint32_t val) {
p[0] = (val >> 24);
p[1] = (val >> 16);
p[2] = (val >> 8);
p[3] = (val >> 0);
}

static uint32_t generate_checksum(unsigned char *block) {
uint32_t sum = 0;

// Clear checksum
write_be(block + 4, 0);

for (int i = 0; i < BOOTBLOCK_SIZE; i += 4) {
uint32_t word = read_be(block + i);
uint32_t old = sum;

sum += word;

if (sum < old) {
sum++;
}
}

return ~sum;
}

int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <bootcode> <adf_output>\n", argv[0]);
return 1;
}

unsigned char buf[ADF_SIZE];
memset(buf, 0, sizeof(buf));

FILE *bootcode = fopen(argv[1], "rb");

if (!bootcode) {
perror("Error opening input file");
return 1;
}

size_t bytes_read = fread(buf + 12, 1, BOOTBLOCK_SIZE - 12, bootcode);

if (ferror(bootcode)) {
perror("Error reading input file");
fclose(bootcode);
return 1;
}

fclose(bootcode);

if (bytes_read == 0) {
fprintf(stderr, "Error: input bootcode binary is empty.\n");
return 1;
}

// 'DOS0' type, 'DOS1' also works
buf[0] = 'D';
buf[1] = 'O';
buf[2] = 'S';
buf[3] = 0x00;

write_be(buf + 4, 0); // checksum
write_be(buf + 8, 880); // root block

uint32_t checksum = generate_checksum(buf);
write_be(buf + 4, checksum);

printf("Calculated checksum: 0x%08X\n", checksum);

FILE *adf_out = fopen(argv[2], "wb");

if (!adf_out) {
perror("Error opening output file");
return 1;
}

size_t written = fwrite(buf, 1, ADF_SIZE, adf_out);

if (written != ADF_SIZE) {
perror("Error writing output file");
fclose(adf_out);
return 1;
}

fclose(adf_out);

printf("Successfully generated ADF image: %s\n", argv[2]);

return 0;
}
117 changes: 117 additions & 0 deletions platform/amiga/display.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright (c) 2026 Josh Cummings
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/

#include "platform_p.h"
#include <dev/display.h>
#include <lib/page_alloc.h>
#include <lk/err.h>
#include <lk/main.h>
#include <platform/display.h>
#include <string.h>
#if WITH_KERNEL_VM
#include <kernel/vm.h>
#else
#include <kernel/novm.h>
#endif

static volatile uint16_t *const paula_base = (void *)0xDFF000;
static struct display_framebuffer display_fb;

// 1bpp bitplane
static uint8_t bitplane[BPL_BYTES];
static uint16_t copper[64];

void make_copper_list(uint8_t *bpl) {
// Bitplane ptr register is two 16bit halves. May need to change this if vm/MMU is ever enabled.
uintptr_t bpl_ptr = (uintptr_t)bpl;
uint16_t bplptr_hi = (bpl_ptr >> 16);
uint16_t bplptr_lo = (bpl_ptr & 0xFFFF);

int i = 0;

// clang-format off

// Copper instructions are two words. First word is the destination register offset, second is the value.

// Set display window
copper[i++] = DIWSTRT; copper[i++] = 0x2C81; // Display window vert + horiz start, PAL low-res mode
copper[i++] = DIWSTOP; copper[i++] = ((((0x2C + H) & 0xFF) << 8) | 0xC1); // vert + horiz end
copper[i++] = DDFSTRT; copper[i++] = 0x0038; // low-res DMA fetch start
copper[i++] = DDFSTOP; copper[i++] = 0x00D0; // DMA fetch stop. Stop and start may need to change if screen width ever does.

// 1 bitplane, enable "colour" output
copper[i++] = BPLCON0; copper[i++] = (0x200 | (1 << 12)); // Set display mode and bitplane count ("BPU"); one bitplane
copper[i++] = BPLCON1; copper[i++] = 0x0000; // No horizontal playfield scroll
copper[i++] = BPLCON2; copper[i++] = 0x0000; // Set playfield priority

// Bitplane modulo = 0 for a single linear bitplane
copper[i++] = BPL1MOD; copper[i++] = 0x0000;
copper[i++] = BPL2MOD; copper[i++] = 0x0000;

// Set bitplane pointer
copper[i++] = BPL1PTH; copper[i++] = bplptr_hi;
copper[i++] = BPL1PTL; copper[i++] = bplptr_lo;

// Background and foreground colours
copper[i++] = COLOR00; copper[i++] = 0x0000;
copper[i++] = COLOR01; copper[i++] = 0x0FFF;

// Send end/terminator words, causes Copper to stop processing the list
copper[i++] = 0xFFFF;
copper[i++] = 0xFFFE;

// clang-format on
}

static void write_reg(unsigned int reg, uint32_t val) {
paula_base[reg >> 1] = val;
}

status_t display_get_framebuffer(struct display_framebuffer *fb) {
fb->image.pixels = bitplane;

fb->image.format = IMAGE_FORMAT_MONO_1;
fb->image.rowbytes = BYTES_PER_ROW;
fb->image.width = W;
fb->image.height = H;
fb->image.stride = BYTES_PER_ROW;
fb->format = DISPLAY_FORMAT_MONO_1;
fb->flush = NULL;

return NO_ERROR;
}

status_t display_get_info(struct display_info *info) {
info->format = DISPLAY_FORMAT_MONO_1;
info->width = W;
info->height = H;

return NO_ERROR;
}

void platform_init_display(void) {
memset(bitplane, 0, BPL_BYTES);

make_copper_list(bitplane);

// Disable DMA
write_reg(DMACON, 0x7FFF);

// Set up copper list address, high and low.
// Physical address, might need revisiting if/when vm/MMU
uintptr_t clist = (uintptr_t)copper;
write_reg(COP1LCH, (clist >> 16));
write_reg(COP1LCL, (clist & 0xFFFF));
write_reg(COPJMP1, 0x0000);

// Enable DMA.
// 0x200 = master DMA enable, 0x100 = bitplane DMA enable, 0x0080 = Copper DMA enable
write_reg(DMACON, (0x8000 | 0x0200 | 0x0080 | 0x0100));

display_get_framebuffer(&display_fb);
}
19 changes: 19 additions & 0 deletions platform/amiga/include/platform/display.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2026 Josh Cummings
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/

#pragma once

enum { W = 320,
H = 256,
// Round up width to next multiple. bitplane DMA is word-aligned (16 pixels).
BYTES_PER_ROW = (((W + 15) & ~15) / 8),
BPL_BYTES = (BYTES_PER_ROW * H) };

void make_copper_list(uint8_t *bpl);
void platform_init_display(void);
void init_display(void);
Loading