first commit

This commit is contained in:
2025-12-01 18:23:49 +01:00
commit 965e10f6b2
20 changed files with 1579 additions and 0 deletions

25
.gitignore vendored Normal file
View File

@@ -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

BIN
.info Normal file

Binary file not shown.

85
README.md Normal file
View File

@@ -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

48
boot.s Normal file
View File

@@ -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

28
boot_debug.s Normal file
View File

@@ -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

27
build.ps1 Normal file
View File

@@ -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

70
custom.i Normal file
View File

@@ -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

162
data.s Normal file
View File

@@ -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

189
game_logic.s Normal file
View File

@@ -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

186
game_simple.s Normal file
View File

@@ -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

170
game_stable.s Normal file
View File

@@ -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

177
graphics.s Normal file
View File

@@ -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

31
info_winuae.py Normal file
View File

@@ -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()

27
input.s Normal file
View File

@@ -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

101
main.s Normal file
View File

@@ -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

62
main_test.s Normal file
View File

@@ -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

63
make_adf.ps1 Normal file
View File

@@ -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"

48
make_adf.py Normal file
View File

@@ -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")

58
test_minimal.s Normal file
View File

@@ -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

22
test_ultra_minimal.s Normal file
View File

@@ -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