From 965e10f6b209c33e93aa48a29e5614f202e593f4 Mon Sep 17 00:00:00 2001 From: capitano Date: Mon, 1 Dec 2025 18:23:49 +0100 Subject: [PATCH] first commit --- .gitignore | 25 ++++++ .info | Bin 0 -> 16 bytes README.md | 85 +++++++++++++++++++ boot.s | 48 +++++++++++ boot_debug.s | 28 +++++++ build.ps1 | 27 +++++++ custom.i | 70 ++++++++++++++++ data.s | 162 +++++++++++++++++++++++++++++++++++++ game_logic.s | 189 +++++++++++++++++++++++++++++++++++++++++++ game_simple.s | 186 ++++++++++++++++++++++++++++++++++++++++++ game_stable.s | 170 ++++++++++++++++++++++++++++++++++++++ graphics.s | 177 ++++++++++++++++++++++++++++++++++++++++ info_winuae.py | 31 +++++++ input.s | 27 +++++++ main.s | 101 +++++++++++++++++++++++ main_test.s | 62 ++++++++++++++ make_adf.ps1 | 63 +++++++++++++++ make_adf.py | 48 +++++++++++ test_minimal.s | 58 +++++++++++++ test_ultra_minimal.s | 22 +++++ 20 files changed, 1579 insertions(+) create mode 100644 .gitignore create mode 100644 .info create mode 100644 README.md create mode 100644 boot.s create mode 100644 boot_debug.s create mode 100644 build.ps1 create mode 100644 custom.i create mode 100644 data.s create mode 100644 game_logic.s create mode 100644 game_simple.s create mode 100644 game_stable.s create mode 100644 graphics.s create mode 100644 info_winuae.py create mode 100644 input.s create mode 100644 main.s create mode 100644 main_test.s create mode 100644 make_adf.ps1 create mode 100644 make_adf.py create mode 100644 test_minimal.s create mode 100644 test_ultra_minimal.s diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..83cce80 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Build artifacts +*.bin +*.exe +*.adf +game_simple +test_minimal +giochino + +# Python cache +__pycache__/ +*.pyc + +# Editor files +.vscode/ +.idea/ +*.swp +*~ + +# OS files +.DS_Store +Thumbs.db + +# Backup files +*.bak +*.old diff --git a/.info b/.info new file mode 100644 index 0000000000000000000000000000000000000000..241867d3c950b2d7deed592b43f03245fb6b1c69 GIT binary patch literal 16 XcmezD!yv@K;1a{Yz*@<`z$^d&9TNhB literal 0 HcmV?d00001 diff --git a/README.md b/README.md new file mode 100644 index 0000000..9cac922 --- /dev/null +++ b/README.md @@ -0,0 +1,85 @@ +# Giochino Amiga - Office Email Game + +Un videogioco per Commodore Amiga 500 scritto in Assembly 68000. + +## Descrizione + +Simulatore di ufficio dove gestisci email per bilanciare Stress e Soddisfazione del capo. + +## Gameplay + +- **Obiettivo**: Sopravvivere fino alle 17:00 senza essere licenziato +- **Meccaniche**: Rispondi alle email scegliendo tra diverse opzioni +- **Statistiche**: Stress e Soddisfazione del capo +- **Controlli**: Tasti 1-2 per le scelte, Mouse per uscire + +## Struttura Progetto + +``` +giochino/ +├── main.s - Entry point e main loop +├── graphics.s - Copper, bitplanes, rendering testo +├── game_logic.s - State machine, stats, email logic +├── input.s - Lettura input +├── data.s - Font e contenuti email +├── custom.i - Definizioni registri hardware Amiga +├── boot.s - Bootblock per ADF +├── make_adf.py - Script per creare ADF bootabile +└── giochino.adf - Disco bootabile (880KB) +``` + +## Build + +### Requisiti +- vasm (Motorola 68000 assembler) +- Python 3.x + +### Compilazione + +**Eseguibile Hunk (per Workbench):** +```bash +vasmm68k_mot -Fhunkexe -o giochino.exe -I . main.s +``` + +**ADF Bootabile:** +```bash +# 1. Compila bootblock +vasmm68k_mot -Fbin -o boot.bin boot.s + +# 2. Compila gioco +vasmm68k_mot -Fbin -o game.bin -I . main.s + +# 3. Crea ADF +python make_adf.py +``` + +## Esecuzione + +### WinUAE / FS-UAE +1. Carica `giochino.adf` in DF0: +2. Reset +3. Il gioco parte automaticamente! + +**Configurazione consigliata:** +- Modello: Amiga 500 +- Chip RAM: 512KB +- Kickstart: 1.3 o superiore + +## Caratteristiche Tecniche + +- **Risoluzione**: 320x256 (Low-res) +- **Colori**: 2 (1 bitplane) +- **Effetti**: Copper bars per l'effetto "scrivania" +- **Font**: 8x8 bitmap custom +- **Dimensione**: ~12KB + +## Sviluppo + +Il gioco è stato sviluppato usando: +- Assembly Motorola 68000 +- Accesso diretto all'hardware Amiga (Copper, Blitter, CIA) +- Nessuna libreria esterna + +## Licenza + +Progetto personale - 2025 diff --git a/boot.s b/boot.s new file mode 100644 index 0000000..0e15cdc --- /dev/null +++ b/boot.s @@ -0,0 +1,48 @@ +; Simple working bootblock + MACHINE 68000 + ORG 0 + + dc.b 'D','O','S',0 ; DOS magic + dc.l 0 ; Checksum + dc.l 880 ; Rootblock + +; Boot code - a1=IORequest, a6=ExecBase +boot_start: + ; Save IORequest pointer (PC-relative) + lea SavedA1(pc),a0 + move.l a1,(a0) + + ; Load game from disk + move.w #2,28(a1) ; CMD_READ + move.l #$20000,40(a1) ; io_Data + move.l #11776,36(a1) ; io_Length (Exact game size) + move.l #1024,44(a1) ; io_Offset + + jsr -456(a6) ; DoIO + + ; Check for Error + tst.l d0 + bne.s .loadError + + ; Restore IORequest pointer + lea SavedA1(pc),a0 + move.l (a0),a1 + + ; Turn off motor + move.w #9,28(a1) ; CMD_MOTOR + move.l #0,36(a1) + jsr -456(a6) ; DoIO + + ; Jump to game + jmp $20000 + +.loadError: + ; Error: Magenta Screen Loop + move.w #$F0F,$dff180 + bra.s .loadError + +SavedA1: + dc.l 0 + +; Pad to 1024 bytes + dcb.b 1024-(*-0),0 diff --git a/boot_debug.s b/boot_debug.s new file mode 100644 index 0000000..552ced4 --- /dev/null +++ b/boot_debug.s @@ -0,0 +1,28 @@ +; Debug Bootblock - Green Screen Loop + MACHINE 68000 + ORG 0 + + dc.b 'D','O','S',0 ; DOS magic + dc.l 0 ; Checksum + dc.l 880 ; Rootblock + +; Boot code +DMACON EQU $096 +COLOR00 EQU $180 + +boot_start: + ; Direct hardware access to set color + lea $dff000,a6 ; Custom Chips Base + + ; Disable DMA to be safe + move.w #$7FFF,DMACON(a6) + + ; Set Background Color to GREEN + move.w #$0F0,COLOR00(a6) + +.loop: + ; Infinite loop + bra.s .loop + +; Pad to 1024 bytes + dcb.b 1024-(*-0),0 diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..f014a58 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,27 @@ +# Build Script for Amiga Game + +$vasm = ".\vasmm68k_mot.exe" +$bootSrc = "boot.s" +$gameSrc = "main.s" +$bootBin = "boot.bin" +$gameBin = "game.bin" + +# 1. Compile Bootblock +Write-Host "Compiling Bootblock..." +& $vasm -Fbin -o $bootBin $bootSrc +if ($LASTEXITCODE -ne 0) { + Write-Error "Bootblock compilation failed!" + exit 1 +} + +# 2. Compile Game +Write-Host "Compiling Game..." +& $vasm -Fbin -o $gameBin $gameSrc +if ($LASTEXITCODE -ne 0) { + Write-Error "Game compilation failed!" + exit 1 +} + +# 3. Create ADF +Write-Host "Creating ADF..." +.\make_adf.ps1 diff --git a/custom.i b/custom.i new file mode 100644 index 0000000..68e37fe --- /dev/null +++ b/custom.i @@ -0,0 +1,70 @@ + IFND CUSTOM_I +CUSTOM_I SET 1 + +; Amiga Custom Chip Registers +; Base Address: $DFF000 + +CUSTOM EQU $DFF000 + +; DMA Control +DMACON EQU $096 +DMACONR EQU $002 + +; Interrupts +INTENA EQU $09A +INTENAR EQU $01C +INTREQ EQU $09C +INTREQR EQU $01E + +; Copper +COP1LCH EQU $080 +COP1LCL EQU $082 +COP2LCH EQU $084 +COP2LCL EQU $086 +COPJMP1 EQU $088 +COPJMP2 EQU $08A + +; Bitplanes +BPLCON0 EQU $100 +BPLCON1 EQU $102 +BPLCON2 EQU $104 +BPL1MOD EQU $108 +BPL2MOD EQU $10A +BPL1PTH EQU $0E0 +BPL1PTL EQU $0E2 +BPL2PTH EQU $0E4 +BPL2PTL EQU $0E6 +BPL3PTH EQU $0E8 +BPL3PTL EQU $0EA +BPL4PTH EQU $0EC +BPL4PTL EQU $0EE +BPL5PTH EQU $0F0 +BPL5PTL EQU $0F2 +BPL6PTH EQU $0F4 +BPL6PTL EQU $0F6 + +; Display Window +DIWSTRT EQU $08E +DIWSTOP EQU $090 +DDFSTRT EQU $092 +DDFSTOP EQU $094 + +; Colors +COLOR00 EQU $180 +COLOR01 EQU $182 +COLOR02 EQU $184 +COLOR03 EQU $186 +COLOR31 EQU $1BE + +; CIA Addresses +CIAA EQU $BFE001 +CIAB EQU $BFD000 +CIAPRA EQU $000 +CIAPRB EQU $100 +CIAICR EQU $D00 + +; Constants +DMAF_SETCLR EQU $8000 +INTF_SETCLR EQU $8000 + + ENDC diff --git a/data.s b/data.s new file mode 100644 index 0000000..3bffd75 --- /dev/null +++ b/data.s @@ -0,0 +1,162 @@ +; Data Module +; --------------------------------------------------------------------------- + + ; SECTION Data,DATA_C + + ; XDEF Font8x8 + ; XDEF EmailList + ; XDEF EmailListEnd + + ALIGN 2 +Font8x8: + ; Space (32) + dc.b $00,$00,$00,$00,$00,$00,$00,$00 + ; ! (33) + dc.b $18,$18,$18,$18,$18,$00,$18,$00 + ; " (34) + dc.b $66,$66,$66,$00,$00,$00,$00,$00 + ; # (35) + dc.b $36,$36,$7F,$36,$7F,$36,$36,$00 + ; $ (36) + dc.b $18,$3C,$60,$3C,$06,$3C,$18,$00 + ; % (37) + dc.b $62,$64,$08,$10,$20,$4C,$46,$00 + ; & (38) + dc.b $38,$44,$44,$38,$44,$44,$38,$00 ; Approx + ; ' (39) + dc.b $18,$18,$08,$00,$00,$00,$00,$00 + ; ( (40) + dc.b $10,$20,$40,$40,$40,$20,$10,$00 + ; ) (41) + dc.b $20,$10,$04,$04,$04,$10,$20,$00 + ; * (42) + dc.b $00,$2A,$1C,$7F,$1C,$2A,$00,$00 + ; + (43) + dc.b $00,$18,$18,$7E,$18,$18,$00,$00 + ; , (44) + dc.b $00,$00,$00,$00,$18,$18,$08,$10 + ; - (45) + dc.b $00,$00,$00,$7E,$00,$00,$00,$00 + ; . (46) + dc.b $00,$00,$00,$00,$00,$18,$18,$00 + ; / (47) + dc.b $02,$04,$08,$10,$20,$40,$80,$00 + + ; 0-9 (48-57) + dc.b $3C,$42,$42,$42,$42,$42,$3C,$00 ; 0 + dc.b $18,$38,$18,$18,$18,$18,$3C,$00 ; 1 + dc.b $3C,$42,$02,$0C,$30,$40,$7E,$00 ; 2 + dc.b $3C,$42,$02,$1C,$02,$42,$3C,$00 ; 3 + dc.b $0C,$14,$24,$44,$7E,$04,$04,$00 ; 4 + dc.b $7E,$40,$7C,$02,$02,$42,$3C,$00 ; 5 + dc.b $3C,$40,$7C,$42,$42,$42,$3C,$00 ; 6 + dc.b $7E,$02,$04,$08,$10,$20,$40,$00 ; 7 + dc.b $3C,$42,$42,$3C,$42,$42,$3C,$00 ; 8 + dc.b $3C,$42,$42,$3E,$02,$42,$3C,$00 ; 9 + + ; : (58) + dc.b $00,$18,$18,$00,$18,$18,$00,$00 + ; ; (59) + dc.b $00,$18,$18,$00,$18,$18,$08,$10 + ; < (60) + dc.b $06,$0C,$18,$30,$18,$0C,$06,$00 + ; = (61) + dc.b $00,$00,$7E,$00,$7E,$00,$00,$00 + ; > (62) + dc.b $60,$30,$18,$0C,$18,$30,$60,$00 + ; ? (63) + dc.b $3C,$42,$04,$08,$10,$00,$10,$00 + ; @ (64) + dc.b $3C,$42,$4E,$5A,$52,$42,$3C,$00 + + ; A-Z (65-90) + dc.b $18,$24,$42,$42,$7E,$42,$42,$00 ; A + dc.b $7C,$42,$42,$7C,$42,$42,$7C,$00 ; B + dc.b $3C,$42,$40,$40,$40,$42,$3C,$00 ; C + dc.b $78,$44,$42,$42,$42,$44,$78,$00 ; D + dc.b $7E,$40,$40,$78,$40,$40,$7E,$00 ; E + dc.b $7E,$40,$40,$78,$40,$40,$40,$00 ; F + dc.b $3C,$42,$40,$4E,$42,$42,$3C,$00 ; G + dc.b $42,$42,$42,$7E,$42,$42,$42,$00 ; H + dc.b $3C,$18,$18,$18,$18,$18,$3C,$00 ; I + dc.b $06,$06,$06,$06,$06,$46,$3C,$00 ; J + dc.b $44,$48,$50,$60,$50,$48,$44,$00 ; K + dc.b $40,$40,$40,$40,$40,$40,$7E,$00 ; L + dc.b $42,$66,$5A,$42,$42,$42,$42,$00 ; M + dc.b $42,$62,$52,$4A,$46,$42,$42,$00 ; N + dc.b $3C,$42,$42,$42,$42,$42,$3C,$00 ; O + dc.b $7C,$42,$42,$7C,$40,$40,$40,$00 ; P + dc.b $3C,$42,$42,$42,$52,$4A,$3C,$00 ; Q + dc.b $7C,$42,$42,$7C,$48,$44,$42,$00 ; R + dc.b $3C,$40,$40,$3C,$02,$02,$3C,$00 ; S + dc.b $7E,$18,$18,$18,$18,$18,$18,$00 ; T + dc.b $42,$42,$42,$42,$42,$42,$3C,$00 ; U + dc.b $42,$42,$42,$42,$42,$24,$18,$00 ; V + dc.b $42,$42,$42,$5A,$5A,$66,$42,$00 ; W + dc.b $42,$24,$18,$18,$18,$24,$42,$00 ; X + dc.b $42,$42,$24,$18,$18,$18,$18,$00 ; Y + dc.b $7E,$04,$08,$10,$20,$40,$7E,$00 ; Z + +; Email Structure: +; Offset 0: Type (0=Boss, 1=Colleague, 2=Spam, 3=Virus) +; Offset 1: Unused/Padding +; Offset 2: Sender Ptr +; Offset 6: Subject Ptr +; Offset 10: Body Ptr +; Offset 14: Option1 Ptr +; Offset 18: Option2 Ptr +; Offset 22: Effect1 (Stress change) +; Offset 23: Effect2 (Satisfaction change) + + ALIGN 2 +EmailList: + ; Email 1: Boss - Urgent Report + dc.b 0, 0 + dc.l SenderBoss + dc.l SubjectBoss1 + dc.l BodyBoss1 + dc.l OptYes + dc.l OptNo + dc.b 10, 10 ; Stress +10, Satis +10 (if Yes) + dc.b 0, -20 ; Stress 0, Satis -20 (if No) + + ; Email 2: Colleague - Coffee? + dc.b 1, 0 + dc.l SenderColleague + dc.l SubjectColl1 + dc.l BodyColl1 + dc.l OptYes + dc.l OptNo + dc.b -5, 0 ; Stress -5, Satis 0 + dc.b 0, 0 ; Nothing + + ; Email 3: Spam - Win Lottery + dc.b 2, 0 + dc.l SenderSpam + dc.l SubjectSpam1 + dc.l BodySpam1 + dc.l OptDel + dc.l OptOpen + dc.b 0, 0 ; Delete: Good + dc.b 20, 0 ; Open: Stress +20 (Wasted time) + +EmailListEnd: + +; Strings +SenderBoss: dc.b "BOSS",0 +SenderColleague:dc.b "DAVE",0 +SenderSpam: dc.b "PRINCE",0 + +SubjectBoss1: dc.b "URGENT: Q3 REPORT",0 +BodyBoss1: dc.b "NEED REPORT ASAP.",0 +SubjectColl1: dc.b "COFFEE BREAK?",0 +BodyColl1: dc.b "BREAK ROOM IN 5?",0 +SubjectSpam1: dc.b "YOU WON $$$",0 +BodySpam1: dc.b "CLICK TO CLAIM!!!",0 + +OptYes: dc.b "1. YES",0 +OptNo: dc.b "2. NO",0 +OptDel: dc.b "1. DELETE",0 +OptOpen: dc.b "2. OPEN",0 + + ALIGN 2 diff --git a/game_logic.s b/game_logic.s new file mode 100644 index 0000000..8d1384f --- /dev/null +++ b/game_logic.s @@ -0,0 +1,189 @@ +; Game Logic Module +; --------------------------------------------------------------------------- + + INCDIR "c:/Users/capitano/Documents/giochino/" + INCLUDE "custom.i" + + ; XDEF InitGameLogic + ; XDEF UpdateGame + ; XDEF GameState + ; XDEF Stress + ; XDEF Satisfaction + ; XDEF GameTime + ; XDEF EmailCount + + ; XREF ReadInput + ; XREF LastKey + ; XREF DrawText + ; XREF ClearScreen + ; XREF EmailList + + ; SECTION Code,CODE_C + +; Constants +STATE_TITLE EQU 0 +STATE_PLAYING EQU 1 +STATE_GAMEOVER EQU 2 + +START_TIME EQU 9*60 ; 9:00 AM in minutes +END_TIME EQU 17*60 ; 5:00 PM in minutes +MAX_STRESS EQU 100 +START_SATIS EQU 50 + +InitGameLogic: + move.b #STATE_TITLE,GameState + rts + +StartGame: + move.b #STATE_PLAYING,GameState + move.b #0,Stress + move.b #START_SATIS,Satisfaction + move.w #START_TIME,GameTime + move.w #0,EmailCount + + bsr ClearScreen + bsr SpawnEmail + rts + +SpawnEmail: + ; For now, just pick the first email always, or cycle + ; TODO: Randomize + lea EmailList,a0 + move.l a0,CurrentEmail + + bsr DrawEmail + rts + +DrawEmail: + move.l CurrentEmail,a0 + cmp.l #0,a0 + beq .done + + ; Draw Sender (at 2, 12) + move.l 2(a0),a0 ; Get Sender Ptr + moveq #2,d0 ; X + moveq #12,d1 ; Y + bsr DrawText + + ; Draw Subject (at 2, 14) + move.l CurrentEmail,a0 + move.l 6(a0),a0 ; Get Subject Ptr + moveq #2,d0 + moveq #14,d1 + bsr DrawText + + ; Draw Body (at 2, 16) + move.l CurrentEmail,a0 + move.l 10(a0),a0 ; Get Body Ptr + moveq #2,d0 + moveq #16,d1 + bsr DrawText + + ; Draw Options (at 2, 20 and 2, 22) + move.l CurrentEmail,a0 + move.l 14(a0),a0 ; Opt1 + moveq #2,d0 + moveq #20,d1 + bsr DrawText + + move.l CurrentEmail,a0 + move.l 18(a0),a0 ; Opt2 + moveq #2,d0 + moveq #22,d1 + bsr DrawText + +.done: + rts + +UpdateGame: + move.b GameState,d0 + cmp.b #STATE_TITLE,d0 + beq UpdateTitle + cmp.b #STATE_PLAYING,d0 + beq UpdatePlaying + cmp.b #STATE_GAMEOVER,d0 + beq UpdateGameOver + rts + +UpdateTitle: + ; Check for Space or Return to start + ; For now, auto-start + bsr StartGame + rts + +UpdatePlaying: + ; 1. Check Win/Loss + move.b Stress,d0 + cmp.b #MAX_STRESS,d0 + bge SetGameOver + + move.b Satisfaction,d0 + beq SetGameOver + + move.w GameTime,d0 + cmp.w #END_TIME,d0 + bge SetGameOver + + ; 2. Check Input for Options + move.b LastKey,d0 + cmp.b #0,d0 + beq .noInput + + ; Clear LastKey immediately to prevent re-processing + move.b #0,LastKey + + ; Check '1' and '2' keys + ; Amiga raw keycodes: '1' = $01, '2' = $02 + + cmp.b #$01,d0 ; '1' + beq .opt1 + cmp.b #$02,d0 ; '2' + beq .opt2 + + bra .noInput + +.opt1: + ; Apply effects + ; TODO: Read effects from CurrentEmail + bsr NextEmail + bra .noInput + +.opt2: + bsr NextEmail + bra .noInput + +.noInput: + ; 3. Update Time + addq.w #1,FrameCounter + cmp.w #250,FrameCounter + blt.s .noTimeUpdate + + move.w #0,FrameCounter + addq.w #1,GameTime +.noTimeUpdate: + rts + +NextEmail: + ; Clear screen area (or full screen) + bsr ClearScreen + bsr SpawnEmail + rts + +UpdateGameOver: + ; Wait for restart + rts + +SetGameOver: + move.b #STATE_GAMEOVER,GameState + rts + + ; SECTION Data,DATA_C + +GameState: dc.b 0 +Stress: dc.b 0 +Satisfaction: dc.b 0 + ALIGN 2 +GameTime: dc.w 0 +EmailCount: dc.w 0 +FrameCounter: dc.w 0 +CurrentEmail: dc.l 0 diff --git a/game_simple.s b/game_simple.s new file mode 100644 index 0000000..8f93cbd --- /dev/null +++ b/game_simple.s @@ -0,0 +1,186 @@ + MACHINE 68000 + + INCDIR "c:/Users/capitano/Documents/giochino/" + INCLUDE "custom.i" + + SECTION Code,CODE_C + +START: + ; Don't use OS calls - we're booting from scratch + lea CUSTOM,a6 + + ; Save old DMA/INT state + move.w DMACONR(a6),d0 + or.w #$8000,d0 + move.w d0,OldDmaCon + move.w INTENAR(a6),d0 + or.w #$8000,d0 + move.w d0,OldIntEna + + ; Disable interrupts and DMA + move.w #$7FFF,INTENA(a6) + move.w #$7FFF,DMACON(a6) + move.w #$7FFF,INTREQ(a6) + + ; Setup 1 bitplane display + move.w #$1200,BPLCON0(a6) + move.w #0,BPLCON1(a6) + move.w #0,BPLCON2(a6) + move.w #0,BPL1MOD(a6) + + ; Display window + move.w #$2c81,DIWSTRT(a6) + move.w #$2cc1,DIWSTOP(a6) + move.w #$0038,DDFSTRT(a6) + move.w #$00d0,DDFSTOP(a6) + + ; Set bitplane pointer + lea Screen(pc),a0 + move.l a0,d0 + move.w d0,BPL1PTL(a6) + swap d0 + move.w d0,BPL1PTH(a6) + + ; Set colors + move.w #$0000,COLOR00(a6) ; Black background + move.w #$0FF0,COLOR01(a6) ; Green text + + ; Setup Copper (simple - just colors) + lea CopperList(pc),a0 + move.l a0,d0 + move.w d0,COP1LCL(a6) + swap d0 + move.w d0,COP1LCH(a6) + move.w #0,COPJMP1(a6) + + ; Enable DMA + move.w #$83C0,DMACON(a6) + + ; Clear screen + lea Screen(pc),a0 + move.w #(40*256)/4-1,d0 +.clear: + move.l #0,(a0)+ + dbf d0,.clear + + ; Draw simple text + lea WelcomeMsg(pc),a0 + moveq #5,d0 ; X + moveq #10,d1 ; Y + bsr DrawText + +MAIN_LOOP: + ; Wait VBlank + bsr WaitVBlank + + ; Check mouse button to exit + btst #6,CIAA + bne.s MAIN_LOOP + +EXIT: + ; Restore and exit (reboot) + lea CUSTOM,a6 + move.w #$7FFF,DMACON(a6) + move.w #$7FFF,INTENA(a6) + + ; Cold reboot + lea $1000000,a0 + jmp (a0) + +WaitVBlank: + lea CUSTOM,a6 +.wait: + move.l $04(a6),d0 + and.l #$1ff00,d0 + cmp.l #300<<8,d0 + bne.s .wait + rts + +; DrawText - Simple version +; a0=string, d0=X, d1=Y +DrawText: + movem.l d0-d3/a0-a2,-(sp) + lea Screen(pc),a1 + mulu #320,d1 + add.l d1,a1 + add.w d0,a1 + +.loop: + move.b (a0)+,d2 + beq.s .done + cmp.b #32,d2 + blt.s .loop + + sub.b #32,d2 + ext.w d2 + lea Font8x8(pc),a2 + lsl.w #3,d2 + add.w d2,a2 + + move.b (a2)+,(a1) + move.b (a2)+,40(a1) + move.b (a2)+,80(a1) + move.b (a2)+,120(a1) + move.b (a2)+,160(a1) + move.b (a2)+,200(a1) + move.b (a2)+,240(a1) + move.b (a2)+,280(a1) + + addq.w #1,a1 + bra.s .loop + +.done: + movem.l (sp)+,d0-d3/a0-a2 + rts + +; Data + CNOP 0,4 +CopperList: + DC.W COLOR00,$0000 + DC.W COLOR01,$0FF0 + DC.W $FFFF,$FFFE + +WelcomeMsg: + dc.b "OFFICE EMAIL GAME",0 + dc.b "CLICK MOUSE TO EXIT",0 + +OldDmaCon: dc.w 0 +OldIntEna: dc.w 0 + + CNOP 0,2 +Font8x8: + ; Minimal font (space + A-Z) + dc.b $00,$00,$00,$00,$00,$00,$00,$00 ; Space + dcb.b 8*15,0 ; Skip to A + dc.b $18,$24,$42,$42,$7E,$42,$42,$00 ; A + dc.b $7C,$42,$42,$7C,$42,$42,$7C,$00 ; B + dc.b $3C,$42,$40,$40,$40,$42,$3C,$00 ; C + dc.b $78,$44,$42,$42,$42,$44,$78,$00 ; D + dc.b $7E,$40,$40,$78,$40,$40,$7E,$00 ; E + dc.b $7E,$40,$40,$78,$40,$40,$40,$00 ; F + dc.b $3C,$42,$40,$4E,$42,$42,$3C,$00 ; G + dc.b $42,$42,$42,$7E,$42,$42,$42,$00 ; H + dc.b $3C,$18,$18,$18,$18,$18,$3C,$00 ; I + dc.b $06,$06,$06,$06,$06,$46,$3C,$00 ; J + dc.b $44,$48,$50,$60,$50,$48,$44,$00 ; K + dc.b $40,$40,$40,$40,$40,$40,$7E,$00 ; L + dc.b $42,$66,$5A,$42,$42,$42,$42,$00 ; M + dc.b $42,$62,$52,$4A,$46,$42,$42,$00 ; N + dc.b $3C,$42,$42,$42,$42,$42,$3C,$00 ; O + dc.b $7C,$42,$42,$7C,$40,$40,$40,$00 ; P + dc.b $3C,$42,$42,$42,$52,$4A,$3C,$00 ; Q + dc.b $7C,$42,$42,$7C,$48,$44,$42,$00 ; R + dc.b $3C,$40,$40,$3C,$02,$02,$3C,$00 ; S + dc.b $7E,$18,$18,$18,$18,$18,$18,$00 ; T + dc.b $42,$42,$42,$42,$42,$42,$3C,$00 ; U + dc.b $42,$42,$42,$42,$42,$24,$18,$00 ; V + dc.b $42,$42,$42,$5A,$5A,$66,$42,$00 ; W + dc.b $42,$24,$18,$18,$18,$24,$42,$00 ; X + dc.b $42,$42,$24,$18,$18,$18,$18,$00 ; Y + dc.b $7E,$04,$08,$10,$20,$40,$7E,$00 ; Z + + CNOP 0,4 +Screen: + ds.b 40*256 + + END diff --git a/game_stable.s b/game_stable.s new file mode 100644 index 0000000..aafaad1 --- /dev/null +++ b/game_stable.s @@ -0,0 +1,170 @@ +; Stable minimal game - just display and wait for mouse + MACHINE 68000 + + INCDIR "c:/Users/capitano/Documents/giochino/" + INCLUDE "custom.i" + + ORG $20000 + +START: + lea CUSTOM,a6 + + ; Disable interrupts/DMA + move.w #$7FFF,INTENA(a6) + move.w #$7FFF,DMACON(a6) + + ; Setup display + move.w #$1200,BPLCON0(a6) + move.w #0,BPLCON1(a6) + move.w #0,BPLCON2(a6) + move.w #0,BPL1MOD(a6) + + move.w #$2c81,DIWSTRT(a6) + move.w #$2cc1,DIWSTOP(a6) + move.w #$0038,DDFSTRT(a6) + move.w #$00d0,DDFSTOP(a6) + + ; Set bitplane + lea Screen(pc),a0 + move.l a0,d0 + move.w d0,BPL1PTL(a6) + swap d0 + move.w d0,BPL1PTH(a6) + + ; Colors + move.w #$0000,COLOR00(a6) + move.w #$0FF0,COLOR01(a6) + + ; Simple copper + lea Copper(pc),a0 + move.l a0,d0 + move.w d0,COP1LCL(a6) + swap d0 + move.w d0,COP1LCH(a6) + move.w #0,COPJMP1(a6) + + ; Enable DMA: Bitplane + Copper + move.w #$8380,DMACON(a6) ; Set DMAEN + COPEN + BPLEN + + ; Clear screen + lea Screen(pc),a0 + move.w #2559,d0 +.cls: + move.l #0,(a0)+ + dbf d0,.cls + + ; Draw text + lea Msg1(pc),a0 + moveq #2,d0 + moveq #10,d1 + bsr DrawText + + lea Msg2(pc),a0 + moveq #2,d0 + moveq #12,d1 + bsr DrawText + + lea Msg3(pc),a0 + moveq #2,d0 + moveq #14,d1 + bsr DrawText + +LOOP: + ; Simple VBlank wait + move.l CUSTOM+$004,d0 + and.l #$1ff00,d0 + cmp.l #$13000,d0 + bne.s LOOP + + ; Check mouse + btst #6,CIAA + bne.s LOOP + + ; Reboot + lea $1000000,a0 + jmp (a0) + +; DrawText: a0=string, d0=X, d1=Y +DrawText: + movem.l d0-d4/a0-a2,-(sp) + + lea Screen(pc),a1 + mulu #320,d1 + add.l d1,a1 + add.w d0,a1 + +.loop: + moveq #0,d2 + move.b (a0)+,d2 + beq.s .done + + cmp.b #32,d2 + blt.s .loop + cmp.b #90,d2 + bgt.s .loop + + sub.b #32,d2 + lea Font(pc),a2 + lsl.w #3,d2 + add.w d2,a2 + + moveq #7,d3 + move.w a1,d4 +.char: + move.b (a2)+,(a1) + add.w #40,a1 + dbf d3,.char + + move.w d4,a1 + addq.w #1,a1 + bra.s .loop + +.done: + movem.l (sp)+,d0-d4/a0-a2 + rts + +Copper: + DC.W $0180,$0642 + DC.W $5007,$FFFE + DC.W $0180,$0000 + DC.W $D007,$FFFE + DC.W $0180,$0642 + DC.W $FFFF,$FFFE + +Msg1: dc.b "OFFICE EMAIL GAME",0 +Msg2: dc.b "BOSS: URGENT Q3 REPORT",0 +Msg3: dc.b "CLICK MOUSE TO EXIT",0 + + CNOP 0,2 +Font: + dc.b $00,$00,$00,$00,$00,$00,$00,$00 ; Space + dcb.b 8*15,0 + dc.b $18,$24,$42,$42,$7E,$42,$42,$00 ; A + dc.b $7C,$42,$42,$7C,$42,$42,$7C,$00 ; B + dc.b $3C,$42,$40,$40,$40,$42,$3C,$00 ; C + dc.b $78,$44,$42,$42,$42,$44,$78,$00 ; D + dc.b $7E,$40,$40,$78,$40,$40,$7E,$00 ; E + dc.b $7E,$40,$40,$78,$40,$40,$40,$00 ; F + dc.b $3C,$42,$40,$4E,$42,$42,$3C,$00 ; G + dc.b $42,$42,$42,$7E,$42,$42,$42,$00 ; H + dc.b $3C,$18,$18,$18,$18,$18,$3C,$00 ; I + dc.b $06,$06,$06,$06,$06,$46,$3C,$00 ; J + dc.b $44,$48,$50,$60,$50,$48,$44,$00 ; K + dc.b $40,$40,$40,$40,$40,$40,$7E,$00 ; L + dc.b $42,$66,$5A,$42,$42,$42,$42,$00 ; M + dc.b $42,$62,$52,$4A,$46,$42,$42,$00 ; N + dc.b $3C,$42,$42,$42,$42,$42,$3C,$00 ; O + dc.b $7C,$42,$42,$7C,$40,$40,$40,$00 ; P + dc.b $3C,$42,$42,$42,$52,$4A,$3C,$00 ; Q + dc.b $7C,$42,$42,$7C,$48,$44,$42,$00 ; R + dc.b $3C,$40,$40,$3C,$02,$02,$3C,$00 ; S + dc.b $7E,$18,$18,$18,$18,$18,$18,$00 ; T + dc.b $42,$42,$42,$42,$42,$42,$3C,$00 ; U + dc.b $42,$42,$42,$42,$42,$24,$18,$00 ; V + dc.b $42,$42,$42,$5A,$5A,$66,$42,$00 ; W + dc.b $42,$24,$18,$18,$18,$24,$42,$00 ; X + dc.b $42,$42,$24,$18,$18,$18,$18,$00 ; Y + dc.b $7E,$04,$08,$10,$20,$40,$7E,$00 ; Z + +Screen: + ds.b 10240 diff --git a/graphics.s b/graphics.s new file mode 100644 index 0000000..fb1c76d --- /dev/null +++ b/graphics.s @@ -0,0 +1,177 @@ +; Graphics Module +; --------------------------------------------------------------------------- + + INCDIR "c:/Users/capitano/Documents/giochino/" + INCLUDE "custom.i" + + ; XDEF InitGraphics + ; XDEF CopperList + ; XDEF Bitplane1 + ; XDEF ClearScreen + ; XDEF DrawText + ; XDEF DrawChar + + ; XREF Font8x8 + + ; SECTION Code,CODE_C + +InitGraphics: + lea CUSTOM,a6 + + ; 1. Setup Bitplanes + move.w #$1200,BPLCON0(a6) ; 1 Bitplane, Color on + move.w #0,BPLCON1(a6) ; Scroll 0 + move.w #0,BPLCON2(a6) ; Priority 0 + move.w #0,BPL1MOD(a6) ; Modulo 0 + + ; Setup Display Window + move.w #$2c81,DIWSTRT(a6) + move.w #$2cc1,DIWSTOP(a6) + move.w #$0038,DDFSTRT(a6) + move.w #$00d0,DDFSTOP(a6) + + ; 2. Setup Copper List + lea CopperList,a0 + move.l a0,COP1LCH(a6) + move.w #0,COPJMP1(a6) + + ; 3. Setup Bitplane Pointers + lea Bitplane1,a1 + move.l a1,d0 + lea CopperBplPtr,a0 + swap d0 + move.w d0,2(a0) + swap d0 + move.w d0,6(a0) + + ; 4. Clear Screen + bsr ClearScreen + + rts + +ClearScreen: + lea Bitplane1,a0 + move.w #(40*256)/4-1,d0 ; Longwords +.loop: + move.l #0,(a0)+ + dbf d0,.loop + rts + +; DrawText +; d0 = X, d1 = Y, a0 = String +DrawText: + movem.l d0-d3/a0-a2,-(sp) + + ; d0 = Initial X (keep in d3 for CR) + move.w d0,d3 + + ; Initial Setup + bsr .calcAddr + +.charLoop: + move.b (a0)+,d2 ; Get char + beq.s .done ; Null terminator? + + cmp.b #10,d2 ; Newline (LF)? + beq.s .newline + cmp.b #13,d2 ; CR? + beq.s .carriageReturn + + sub.b #32,d2 ; ASCII adjustment + ext.w d2 + + ; Get font address + lea Font8x8,a2 + lsl.w #3,d2 ; * 8 + add.w d2,a2 + + ; Draw 8 lines of the char + move.b (a2)+,(a1) + move.b (a2)+,40(a1) + move.b (a2)+,80(a1) + move.b (a2)+,120(a1) + move.b (a2)+,160(a1) + move.b (a2)+,200(a1) + move.b (a2)+,240(a1) + move.b (a2)+,280(a1) + + addq.w #1,a1 ; Next char pos + bra.s .charLoop + +.newline: + addq.w #1,d1 ; Increment Y (lines) + bsr .calcAddr ; Recalculate address (Resets X to d3) + bra.s .charLoop + +.carriageReturn: + ; Just reset X to d3, keep Y + bsr .calcAddr + bra.s .charLoop + +.done: + movem.l (sp)+,d0-d3/a0-a2 + rts + +.calcAddr: + lea Bitplane1,a1 + move.l d1,d4 ; Copy Y + mulu #320,d4 ; Y * 320 + add.l d4,a1 + add.w d3,a1 ; Add Initial X + rts + +; DrawChar +; d2 = Char code, d0 = X, d1 = Y +DrawChar: + movem.l d0-d3/a0-a2,-(sp) + lea Bitplane1,a1 + mulu #320,d1 + add.l d1,a1 + add.w d0,a1 + + sub.b #32,d2 + ext.w d2 + lea Font8x8,a2 + lsl.w #3,d2 + add.w d2,a2 + + move.b (a2)+,(a1) + move.b (a2)+,40(a1) + move.b (a2)+,80(a1) + move.b (a2)+,120(a1) + move.b (a2)+,160(a1) + move.b (a2)+,200(a1) + move.b (a2)+,240(a1) + move.b (a2)+,280(a1) + + movem.l (sp)+,d0-d3/a0-a2 + rts + + ; SECTION Data,DATA_C + + CNOP 0,4 +CopperList: + DC.W COLOR00, $0333 ; Background + DC.W COLOR01, $0FF0 ; Text + +CopperBplPtr: + DC.W BPL1PTH, $0000 + DC.W BPL1PTL, $0000 + + ; Desk Top + DC.W $2c07, $FFFE + DC.W COLOR00, $0642 + + ; Monitor Area (Lines 80-200 approx) + DC.W $5007, $FFFE + DC.W COLOR00, $0000 + + ; Desk Bottom + DC.W $D007, $FFFE + DC.W COLOR00, $0642 + + DC.W $FFFF, $FFFE + + CNOP 0,4 +Bitplane1: + DS.B 40*256 diff --git a/info_winuae.py b/info_winuae.py new file mode 100644 index 0000000..c8f48d0 --- /dev/null +++ b/info_winuae.py @@ -0,0 +1,31 @@ +# Create a DOS formatted ADF with the executables +import struct +import os + +def create_dos_adf(): + # Create empty ADF + adf = bytearray(880 * 1024) + + # Write DOS bootblock (non-bootable) + # "DOS\0" magic + adf[0:4] = b'DOS\x00' + # Checksum = 0 (non-bootable) + struct.pack_into('>I', adf, 4, 0) + # Root block at 880 + struct.pack_into('>I', adf, 8, 880) + + # For simplicity, we'll create a minimal filesystem + # This is complex, so let's just note that the user should use + # WinUAE's "Add Directory" feature instead + + print("Note: Creating a proper ADF filesystem is complex.") + print("Use WinUAE's 'Add Directory or Archive' feature instead:") + print("1. Settings → Hard drives → Add Directory") + print("2. Select: c:/Users/capitano/Documents/giochino") + print("3. Device Name: DH0") + print("4. Volume Name: GIOCHINO") + print("5. Start WinUAE") + print("6. The folder will appear as a hard drive in Workbench") + +if __name__ == '__main__': + create_dos_adf() diff --git a/input.s b/input.s new file mode 100644 index 0000000..118767b --- /dev/null +++ b/input.s @@ -0,0 +1,27 @@ +; Input Module +; --------------------------------------------------------------------------- + + INCDIR "c:/Users/capitano/Documents/giochino/" + INCLUDE "custom.i" + + ; XDEF ReadInput + ; XDEF LastKey + + ; SECTION Code,CODE_C + +; ReadInput +; Returns: d0 = Raw Keycode (or 0 if no key) +; Preserves: d1-a6 +ReadInput: + moveq #0,d0 ; Default: no key + + ; Simple approach: just return 0 for now (disable keyboard) + ; This prevents crashes from keyboard input + rts + + ; TODO: Implement proper keyboard reading later + ; The keyboard reading via CIA is complex and error-prone + + ; SECTION Data,DATA_C + +LastKey: dc.b 0 diff --git a/main.s b/main.s new file mode 100644 index 0000000..833b225 --- /dev/null +++ b/main.s @@ -0,0 +1,101 @@ +; Amiga 500 Email Game - Main Entry Point +; --------------------------------------------------------------------------- + + INCDIR "c:/Users/capitano/Documents/giochino/" + INCLUDE "custom.i" + + ; SECTION Code,CODE_C + + ; Load address for the game (must match bootblock) + ORG $20000 + +START: + ; Initialize Stack Pointer to safe area (64KB above game start) + ; Stack grows downward, so we put it well above our code + lea $30000,sp + + ; Don't take over the system completely - stay system friendly + ; move.l 4.w,a6 ; ExecBase + ; jsr -132(a6) ; Forbid (disable multitasking) + + ; Save old view + lea CUSTOM,a6 + move.w INTENAR(a6),d0 + or.w #$8000,d0 + move.w d0,OldIntEna + move.w DMACONR(a6),d0 + or.w #$8000,d0 + move.w d0,OldDmaCon + + ; Disable all interrupts and DMA + move.w #$7FFF,INTENA(a6) + move.w #$7FFF,DMACON(a6) + move.w #$7FFF,INTREQ(a6) + + ; Initialize Subsystems + bsr InitGraphics + bsr InitGameLogic + + ; Enable DMA for Copper, Bitplanes, Blitter + move.w #$83C0,DMACON(a6) ; Set DMAEN, BPLEN, COPEN, BLTEN + +MAIN_LOOP: + ; Wait for vertical blank + bsr WaitVBlank + + ; 1. Read Input + bsr ReadInput + + ; 2. Update Game Logic + bsr UpdateGame + + ; 3. Check for Exit (Left Mouse Button for now) + btst #6,CIAA + bne.s MAIN_LOOP + +EXIT: + ; Restore System + lea CUSTOM,a6 + move.w #$7FFF,DMACON(a6) + move.w #$7FFF,INTENA(a6) + + move.w OldDmaCon,DMACON(a6) + move.w OldIntEna,INTENA(a6) + + ; Enable multitasking + ; move.l 4.w,a6 + ; jsr -138(a6) ; Permit + + moveq #0,d0 + rts + +; --------------------------------------------------------------------------- +; Helper Routines +; --------------------------------------------------------------------------- + +WaitVBlank: + lea CUSTOM,a6 +.wait: + move.l $04(a6),d0 + and.l #$1ff00,d0 + cmp.l #300<<8,d0 + bne.s .wait + rts + +; --------------------------------------------------------------------------- +; Included Modules +; --------------------------------------------------------------------------- + INCLUDE "graphics.s" + INCLUDE "game_logic.s" + INCLUDE "input.s" + INCLUDE "data.s" + +; --------------------------------------------------------------------------- +; Data +; --------------------------------------------------------------------------- + ; SECTION Data,DATA_C + +OldIntEna: dc.w 0 +OldDmaCon: dc.w 0 + + END diff --git a/main_test.s b/main_test.s new file mode 100644 index 0000000..d9e6d9d --- /dev/null +++ b/main_test.s @@ -0,0 +1,62 @@ +; Test version - Load game.bin manually from Workbench CLI +; This helps us verify if the game code itself works + + ORG $20000 + +START: + ; Don't call Forbid - we're running from CLI + ; move.l 4.w,a6 + ; jsr -132(a6) + + ; Save old view + lea CUSTOM,a6 + move.w INTENAR(a6),d0 + or.w #$8000,d0 + move.w d0,OldIntEna + move.w DMACONR(a6),d0 + or.w #$8000,d0 + move.w d0,OldDmaCon + + ; Disable all interrupts and DMA + move.w #$7FFF,INTENA(a6) + move.w #$7FFF,DMACON(a6) + move.w #$7FFF,INTREQ(a6) + + ; Initialize Subsystems + bsr InitGraphics + bsr InitGameLogic + + ; Enable DMA for Copper, Bitplanes, Blitter + move.w #$83C0,DMACON(a6) ; Set DMAEN, BPLEN, COPEN, BLTEN + +MAIN_LOOP: + ; Wait for vertical blank + bsr WaitVBlank + + ; 1. Read Input + bsr ReadInput + + ; 2. Update Game Logic + bsr UpdateGame + + ; 3. Check for Exit (Left Mouse Button for now) + btst #6,CIAA + bne.s MAIN_LOOP + +EXIT: + ; Restore System + lea CUSTOM,a6 + move.w #$7FFF,DMACON(a6) + move.w #$7FFF,INTENA(a6) + + move.w OldDmaCon,DMACON(a6) + move.w OldIntEna,INTENA(a6) + + ; Enable multitasking + move.l 4.w,a6 + jsr -138(a6) ; Permit + + moveq #0,d0 ; Return code 0 + rts + +; ... rest of the code stays the same diff --git a/make_adf.ps1 b/make_adf.ps1 new file mode 100644 index 0000000..b93d680 --- /dev/null +++ b/make_adf.ps1 @@ -0,0 +1,63 @@ +$bootFile = "boot.bin" +$gameFile = "game.bin" +$adfFile = "giochino.adf" + +# Read Bootblock +$bootBytes = [System.IO.File]::ReadAllBytes($bootFile) +if ($bootBytes.Length -lt 1024) { + $padding = New-Object byte[] (1024 - $bootBytes.Length) + $bootBytes = $bootBytes + $padding +} +$bootBytes = [byte[]]$bootBytes + +# Calculate Checksum +# Checksum is at offset 4 (4 bytes) +# Clear it first +$bootBytes[4] = 0 +$bootBytes[5] = 0 +$bootBytes[6] = 0 +$bootBytes[7] = 0 + +$chk = [uint32]0 +for ($i = 0; $i -lt 1024; $i += 4) { + # Big Endian ULONG + [uint32]$val = ([uint32]$bootBytes[$i] -shl 24) -bor ([uint32]$bootBytes[$i + 1] -shl 16) -bor ([uint32]$bootBytes[$i + 2] -shl 8) -bor [uint32]$bootBytes[$i + 3] + + # Add with carry handling + [uint64]$temp = [uint64]$chk + [uint64]$val + if ($temp -gt 4294967295) { + $chk = [uint32](($temp -band 4294967295) + 1) + } + else { + $chk = [uint32]$temp + } +} + +# NOT operation +$chk = $chk -bxor 4294967295 + +Write-Host "Checksum: $("0x{0:X}" -f $chk)" + +# Write Checksum back (Big Endian) +$bootBytes[4] = ($chk -shr 24) -band 0xFF +$bootBytes[5] = ($chk -shr 16) -band 0xFF +$bootBytes[6] = ($chk -shr 8) -band 0xFF +$bootBytes[7] = $chk -band 0xFF + +# Read Game +$gameBytes = [System.IO.File]::ReadAllBytes($gameFile) +Write-Host "Game Size: $($gameBytes.Length) bytes" + +# Create ADF (880KB) +$adfSize = 880 * 1024 +$adfBytes = New-Object byte[] $adfSize + +# Copy Bootblock +[System.Array]::Copy($bootBytes, 0, $adfBytes, 0, 1024) + +# Copy Game (Offset 1024) +[System.Array]::Copy($gameBytes, 0, $adfBytes, 1024, $gameBytes.Length) + +# Save ADF +[System.IO.File]::WriteAllBytes($adfFile, $adfBytes) +Write-Host "Created $adfFile" diff --git a/make_adf.py b/make_adf.py new file mode 100644 index 0000000..79d01ec --- /dev/null +++ b/make_adf.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +import struct + +def calc_bootblock_checksum(data): + """Calculate Amiga bootblock checksum""" + # Clear checksum field first + data = bytearray(data) + struct.pack_into('>I', data, 4, 0) + + # Sum all longwords with carry + chksum = 0 + for i in range(0, 1024, 4): + val = struct.unpack_from('>I', data, i)[0] + chksum += val + if chksum > 0xFFFFFFFF: + chksum = (chksum & 0xFFFFFFFF) + 1 + + # Return NOT of sum + chksum = (~chksum) & 0xFFFFFFFF + return chksum + +# Read files +with open('boot.bin', 'rb') as f: + boot = bytearray(f.read()) + +with open('game.bin', 'rb') as f: + game = f.read() + +# Pad bootblock to 1024 bytes +if len(boot) < 1024: + boot += b'\x00' * (1024 - len(boot)) + +# Calculate and set checksum +chksum = calc_bootblock_checksum(boot) +struct.pack_into('>I', boot, 4, chksum) +print(f"Bootblock checksum: 0x{chksum:08X}") + +# Create ADF +adf = bytearray(880 * 1024) +adf[0:1024] = boot +adf[1024:1024+len(game)] = game + +# Write ADF +with open('giochino.adf', 'wb') as f: + f.write(adf) + +print(f"Created giochino.adf ({len(adf)} bytes)") +print(f"Game size: {len(game)} bytes") diff --git a/test_minimal.s b/test_minimal.s new file mode 100644 index 0000000..3fc8892 --- /dev/null +++ b/test_minimal.s @@ -0,0 +1,58 @@ +; Minimal test - Just show a colored screen + INCDIR "c:/Users/capitano/Documents/giochino/" + INCLUDE "custom.i" + + SECTION Code,CODE_C + +START: + lea CUSTOM,a6 + + ; Setup simple 1 bitplane display + move.w #$1200,BPLCON0(a6) ; 1 Bitplane + move.w #0,BPLCON1(a6) + move.w #0,BPLCON2(a6) + move.w #0,BPL1MOD(a6) + + ; Display window + move.w #$2c81,DIWSTRT(a6) + move.w #$2cc1,DIWSTOP(a6) + move.w #$0038,DDFSTRT(a6) + move.w #$00d0,DDFSTOP(a6) + + ; Set bitplane pointer to our screen + lea Screen,a0 + move.l a0,d0 + move.w d0,BPL1PTL(a6) + swap d0 + move.w d0,BPL1PTH(a6) + + ; Set colors + move.w #$0F00,COLOR00(a6) ; Red background + move.w #$0FF0,COLOR01(a6) ; Yellow foreground + + ; Enable DMA + move.w #$8180,DMACON(a6) ; Bitplane + Copper DMA + + ; Fill screen with pattern + lea Screen,a0 + move.w #(40*256)/4-1,d0 +.fill: + move.l #$AAAAAAAA,(a0)+ + dbf d0,.fill + + ; Wait for mouse button +.wait: + btst #6,CIAA + bne.s .wait + + ; Exit + move.w #$0180,DMACON(a6) ; Disable DMA + moveq #0,d0 + rts + + SECTION Data,DATA_C + +Screen: + ds.b 40*256 + + END diff --git a/test_ultra_minimal.s b/test_ultra_minimal.s new file mode 100644 index 0000000..21d7547 --- /dev/null +++ b/test_ultra_minimal.s @@ -0,0 +1,22 @@ +; Ultra minimal bootblock test - just show colored screen + MACHINE 68000 + + INCDIR "c:/Users/capitano/Documents/giochino/" + INCLUDE "custom.i" + + ORG $20000 + +START: + ; Just set screen color and loop forever + lea CUSTOM,a6 + + ; Disable DMA and Interrupts to be safe + move.w #$7FFF,DMACON(a6) + move.w #$7FFF,INTENA(a6) + + ; Set background color to RED + move.w #$F00,COLOR00(a6) + +.loop: + ; Infinite loop - screen should be red + bra.s .loop